It’s that time of the year when React enthusiasts and Next.js fans tune into the annual Next.js Conference to hear from its creators and a team of talented engineers from both the company and the community about the latest additions to the framework and the directions it’s heading
Next.js Conf was followed by thousands of engineers online on Oct 26 and accompanied by the main event in San Francisco, as well as numerous watch parties around the world. We, as a Next.js specialized agency, were right in the thick of it, soaking in the latest and greatest.
In this recap, we're bringing you the highlights, game-changing announcements, and expert insights that illuminated the event. We'll dive deep into the Next.js 14 release, exploring the newest trends and techniques that are poised to shape the future of web development.
Let’s dive in
While the main conference theme was the focus on stability with “no new API’s” statement, there is a lot to unwrap as the key concepts that are now becoming stable, will be the foundation for future React and Next.js applications.
You can follow the full sessions in the live stream recordings on youtube:
Agenda and conference page can be found here.
One of the fascinating facts shared in the opener, they’ve counted a whooping 850k monthly active users of Next.js. So you’re not alone on this journey!
Keynote by Guillermo Rauch, creator of Next.js and founder of Vercel
Important context that Guillermo emphasizes on is that Next.js strength is in it’s zero configuration concept and opinionated, yet powerful core feature set, all while it is fundamentally built on top of React (the library) own concepts that are applicable widely across different frameworks and JS apps.
The initial exposition made us feel that this presentation is the missing React keynote, rather than Next.js. And it is an important detail when it comes to React Server Components and React Server Actions which brings the React’s Component Model a big step further:
One of my React favorite features is the ability to compose into reusable components (quote Guillermo Rauch)
Let’s first summarize the key points covered and break them down with more details below:
- Server Actions are now stable
- Announcement of partial (static) pre-rendering
- Update on Rust compiler status, Turbopack, for Next.js, that promises significant build and dev environment improvements
- Launch of new docs and learning hub - nextjs.org/learn
React Server Actions has been earlier announced by the React core team, and just recently landed into React Canary version. But what’s Canary in React, is Stable in Next.js.
Next.js positions Server Actions as a stable API in its implementation, and has been highlighted as “the missing peace of the puzzle” by Guillermo through his talk.
we were limited by the client side, but recently we got hooks and now the next step is server actions (by Guillermo Rauch)
this required a bunch of things - new router, new data fetching system (with sophisticated caching), streaming architecture (by Guillermo Rauch)
It is one of the foundational pieces that will shape the React ecosystem going forward, and brings React’s composability concept even further, making it’s easier to share “full stack” components with encapsulated data SDK’s without requiring to accompany UI elements with own data fetching and unnecessary boilerplate code.
More on what’s expected from Server Actions covered in the following presentations.
Partial Static Prerendering
While no new API’s announced, Next.js still packs a few underlying features that work out of the box, thanks to a sophisticated compiler that can now extract static shell for each entry points of the app, including dynamic pages.
This allows to greatly improve the loading of initial visual as fastest as you possibly can, with all placeholders rendered from a static cache, including Suspense fallbacks. Best part - it’ just works without requiring any boilerplate code.
As seen on the slide below, the initial load is instant, followed by the dynamic part of the page.
The ability to combine both dynamic and static in a hybrid manner was always the strongest part of Next.js compared to it’s rivals, now this feature brings the framework even further ahead in it’s ability to compile the best possible performant combination of various “chunks” sent over the wire.
More details about Partial Rendering in the recap shared from a community member and the release blog post.
Following last year’s announcement of Rust compiler coming to replace Webpack, Guillermo shared updates on their continuous efforts of improving build and development runtime performance.
While it’s still work in progress they state that while testing on Vercel website, they’ve seen an improvement of:
- Up to 53.3% faster local server startup
- Up to 94.7% faster code updates with Fast Refresh
You can try it yourself behind the flag
next dev --turbo, and with +90% of tests passing, it’s closer than ever to the stable release. You can follow the progress of how close is the Rust compiler to the stable release here: https://areweturboyet.com
How Next.js is delivering React's vision for the future by Sam Selikof
In this presentation, Sam discusses the evolution of React and Next.js, introducing new features for developers that were previously either unavailable or less convenient.
The presentation kicks off with a React Single Page Application (SPA) code example and emphasizes the convenience of working with component composition, especially when leveraging hooks like useSWR.
If our application requires Server-Side Rendering (SSR), this approach is no longer applicable, as the data needs to be loaded on the server. Therefore, we need to utilize the getServerSideProps method.
With this approach, we lose the composition that we all love in React, because we need to pass data and it's not as straightforward to insert these components anywhere.
Thanks to server-side components, now we can regain this capability and reap all the benefits of composition and SSR approach.
We now have the ability to call server actions directly within the component, which makes the code more secure, convenient, and readable.
In conclusion, Sam emphasizes that with modern tools, we not only have the capability to leverage the best aspects of existing approaches, but also to create new, unique features that were previously unavailable, treating them like ordinary UI packages from npm.
Optimizing Third-Party Loading in Next.js by Houssein Djerdeh
For several years now, Houssein and his team have been working in collaboration with Next.js. Through collective efforts, they have introduced tools such as
next/font, which are used in the majority of Next.js projects.
He addresses the issue of third-party dependencies, which are commonly used in most internet resources, as they have a significant impact on the overall performance of the resources. Here are a few examples of metrics dependencies on the amount of resources added to a project.
Incorporating such third-party resources can be made more efficient by utilizing the
next/script component, as it encompasses a range of optimizations and tools, such as "strategy"' which greatly aids in optimizing the loading of these scripts.
The only bottleneck with this approach is that it's not always clear how to precisely employ
next/script with a specific third-party resource. Which strategy is best to choose? Where should the script itself be added?
To address this issue, Houssein and his team are working on the
@next/third-parties library, which is currently in active development. They conduct their own performance research to ensure you get the best outcome. Consequently, adding, for example, Google Tag Manager can become incredibly straightforward, while also giving you confidence that this method of integration is the most effective and optimized.
The Big Headless CMS Lie by James Mikrut
James gave a talk from the perspective of the founder of Payload, an Open Source Headless CMS platform. We found this topic to be especially close to us, as we specialize on a variety of different Headless CMS and consulted multiple clients on the subject.
Building with Headless CMS was always a more complex technical process compared to traditional options Like Wordpress, trading convenience of complete system of tightly knit modules (like in Wordpress) for a full bespoke flexibility of Headless-first solutions, at a cost of development time and budget. The talk starts with a fair criticism of excuses developers and agencies made to convince their clients going for Headless, while pointing that the main goal was mostly about using Next.js as a decoupled frontend.
The story continued with some examples of how it would be more convenient for some Headless-first vendors, including themselves at Payload, to move back to more monolithic frameworks like Next.js.
It is true that at this level of performance and sophistication of web development, it makes sense to get back to the roots and centralize around frameworks, instead of rebuilding the same thing again. But the main idea is that the current iteration of Next.js enables best of both worlds - convenience of the framework and flexibility that would even allow running it as a pure Backend even for those who don’t want to have a client-facing Next.js app.
After going through some specific examples, that we won’t cover in this recap, the conclusions made were about the possibilities that React Server Components and Server Actions unlock, that would allow various vendors to build more solutions on top of Next.js not around it.
Performance in React and Next.js by Lydia Hallie
During the presentation, Lydia speaks about the concurrent features that have been introduced in React 18 and how NextJS leverages these features to provide better performance out of the box.
In this demo we have a very long list of cities which is being rerendered on each keystroke and since we have a lot of expensive calculations, the performance is suffering.
We could use debounce libraries to resolve this, but no solution was built in React itself so far.\
React 18 introduces concurrent features which allow us to mark components as low priority to improve performance. While rendering such components React will yield to the main thread every 5ms to ensure that there are no more important tasks to execute.
For example, we can mark a state change as a low priority with useTransition. Then React will interrupt the render caused by this change if some more important interaction comes along.
This demo uses Transition. The performance metrics got much better.
Another way to manage components priority is to use Suspense boundary as it is always treated as low priority.
With SSR we are able to send one request for the page with all data in it, so there is no need to wait until the JS code is loaded and run the data request.
Besides rendering updates, React introduces new ways to memoize data or data fetching results. To do this we can either use the new cache function or the enhanced fetch API.
The new fetch API usage example:
In this case, React will store the results in an in-memory cache and reuse these results if some other component requires the same data.
NextJS new features
NextJS prerenders the components that do not require request-based data at the build time. For the components that do require request-based data, we can create an implicit Suspense boundary just by adding a loading.js file. Its exported value will be used as the fallback.
Also, NextJS introduces Partial prerendering. Up until now we could have either entirely static routes or pages rendered entirely dynamically. There was no way to give this dynamism to the child components of static routes. And Partial prerendering makes it possible. So it prerenders all the components outside of the Suspense boundary which contains the dynamic component statically and very quickly, and then, it renders the dynamic component as soon as it becomes ready.
Unlocking Composable Content with the App Router by Kapehe and Grant Sander
Kapehe and Grant delve into their experiences and best practices using the
next-sanity package inside the Next.js App Router and major challenges faced during the migration.
Grant mentioned that most of the challenges with migration to Next.js 13 were due to incompatibilities with some open-source libraries. Many of them were initially incompatible with React Server components, presenting a tricky migration path. However, with the help of the community, many early issues had been solved.
next-sanity package, developers can now embed the Sanity Studio directly into their Next.js applications. Grant described the simplicity of this integration, stating that it makes it easier for both developers and content editors. Now, they don't need separate repositories for the studio and frontend, streamlining the development and deployment process.
Using Next.js Revalidate Tag, he showed how to revalidate Sanity data at the component level and explained how caching and revalidation work in tandem.
next-sanity library simplifies many of these caching and invalidation processes. It provides functionalities like tagging fetch requests, handling security with payload validation, and abstracting the cache invalidation logic, making it much more streamlined for developers.
Grant explained the benefits of on-demand revalidation and shared implementation details. When content editors make changes in the Sanity Studio, webhooks are set up to ensure the updated content is immediately available on the website.
The things Vercel won't show you by Theo
Theo talks through the unique patterns, that are not typically recommended and could be problematic, but still, might be useful for the specific use cases.
Patterns are sorted in a specific order, from totally viable ones to the most cursed.
The first example is a simple next js app with the pagination
DataView takes initialData prop. The value provided to the
initialData prop is a server action function call, that returns the pagination array as a result.
DataView component is a client component, that has a state, to store data after loading, and loadMore handler, that loads new data. Because of the provided initial data, the pagination UI is ready on the server. This prevents us from unpleasant layout shifts.
Server action can be called anywhere on the client, because it is effectively compiledinto into a rpc call. In addition to that, it's type-safe.
globalThis as an SSR helper
This pattern helps you to pass server context to the client, without directly passing the prop
The demo shows a page server component with fetched data,
GlobalThisEmbedder, and a Client component.
Client component takes the data from globalThis, and render it on the client.
`GlobalThisEmbedder takes server fetched data as a props and set it to both server and client globalThisContexts. Fairly easy in case of server context: simply assigning prop value to the globalThis. A bit tricky for a client context: inside useServerInsertedHTML hook declare a script, that takes stringified server content (same as with server context, but with stringified value) data and return script tag with dangerously set inner html props equal to declared stringified script value.
useServerInsertedHTML ensure code will be run on server even tho used in the client component.
Most of the time you will never need something like this, but if you do it's incredibly helpful.
function* for streaming component updates
This pattern is exclicitelly not recomended by vercel team.
Demo shows how to stream updates to the component, using generator functions.
How does it work?
Generator component takes previous results and uses it as a fallback for Suspense. Then calls itself recursively with the generator, using values that are being yielded. In addition to that it doesn't resolve suspense until the last value inside generator is reached.
The use case for this could be a component, that fetches multiple different states on the server during one fetch, this could be useful.