Next.js 13 is now available – big changes and a new build system
Yesterday Vercel announced Next.js, the latest version of their server-powered React platform.
The central conceit in tools like Next.js is that client-side-only single page applications are not adequate for building responsive web applications. They all build on the concepts laid down by Gatsby and other JamStack platforms: generate (and pre-render) content ahead of time, provide routes to individual content pages just like a regular website, and then use React once the page is loaded to provide a superior user experience.
So if we accept the premise that application servers with server-rendered HTML pages swung the pendulum too far to the right, and sacrificed usability, developer experience and user experience for speed, and that SPAs pushed to the left, with the interactivity suffering because of large deployment sizes, too many http requests, and difficulty in handling static content, a tool like Next.js should put the pendulum back in the center, allowing for both client and server to do what they do best.
Enter Next.js – the client/server application platform
Next.js has been picked by very big companies, such as Walmart and Target, to handle their large-scale content-rich websites. It has inspired other developers, creating tools such as Remix.run and Nuxt (a vue-based competitor). But what sets Next.js apart is their focus on performance, girded by their hosting business at Vercel. Every decision the team makes appears to support better serving developers and devops / site reliability engineers and solving many of the problems that plague developers across all platforms.
Next.js began by providing a framework for predictable universal React.js (running on both the client and the server). Some of the earliest features included running the routed-to view as a server-rendered page, then downloading it to the client. This pre-rendered view automatically bootstraps the rest of the application asynchronousy, so that by the time the user clicks on the next page-navigating action, the application is ready to go.
We should define several terms here:
Server Side Generation– SSG – generating static pages at build time, the content for fast HTML while allowing the application to boot quickly behind the scenes.
Server Side Rendering– SSR – at runtime, perform queries on the server-side, pre-rendering the content for fast, query-specific HTML rendering before serving to the client.
We'll use those terms in acronym form below.
GraphQL and REST to build up pages. Once the page was booted, React applications could then be booted to provide dynamic operations as per usual.
At the time it was created, Next.js lapped Gatsby and other JamStack platforms by providing Server-side Rendering (SSR). Next.js subsequently added Server Side Generation and even Incremental Site Generation features to their platform to provide build and runtime based page generation.
Another innovation was Vercel's own components that are Next.js-aware, such as the
<Script />. The
<Image /> component optimizes images at build time for quick delivery at the appropriate resolutions, where the
<Link /> component provides client-side transitions, enabling pre-fetch of the routed-to content (this can be disabled where appropriate) to eliminiate latency between navigation events.
The team adopted a Rust-based build tool,
swc, to dramatically decrease build times. In fact, Vercel then hired the creator who has integrated
swc into Next.js. They also hired Tobias Koppers, the creator of Webpack, for reasons that will become evident below.
There are many other innovations here, including their public wrestling with React 18 server-side components over the past year, and coming to terms with them in this new release by adoptiong the latest React 18 Server module conventions RFC.
Let's look at what they announced yesterday.
What's new for Next 13?
The Next.js team announced three major changes: a new build tool named Turbopack, a (may I say Remix.run-inspired) new layout engine with an opt-in
/app folder structure and React 18 server components built in, and some significantly updated components.
The Turbopack build system
This feature caused quite a bit of consternation in the Discord, since it was released without support of some key developer tools such as Tailwind CSS and Storybook. However, this is an alpha preview, only opted-in by adding
--turbo to your
next run command. The team is working on this primarily for developer experience at this time, and adding in production build support in the future.
Since it is a rust-based Webpack replacement, developed by the creator of Webpack, the developer is keenly aware of what needs to be done.It aims to marry the developer, framework and user experiences, by providing better error handling, superior HMR, a more composable build configuration (than Webpack), advanced treeshaking (and eliminating a separate Rollup build for production), and faster app loading.
Strong goals, there… I personally find Webpack configuration hopelessly confusing. It reminds me of the early Spring Framework complexity of ACEGI (the security API) where only a few people knew how to magically wire it together, until they focused on developer productivity and added the security namespace. But I digress.
Since it breaks existing build systems, it's not advised to opt-in all the way. Consider this a preview alpha, as the team has forced you to opt in to try it out. However, once platform support is added for the existing Webpack ecosystem (something also on their list of goals), and once production builds are ready to go, this should be an interesting alternative (and hopefully much simpler) build system to work with.
Here is an excellent conference talk from Maia Teegarden on Turbopack for your enjoyment. It covers the history of bundlers and transpilers, and why Turbopack exists. She goes into what it is, and it does now, and what it will do in the future.
The new Layout engine
I wonder if the team at Remix.run's ears are burning… They should be, as their innovations in nested routing provided a great nested routes solution and improved data loading with a very nice server-rendered web APIs approach to data fetching.
In Next.js, the layout engine (enabled by creating a
/app folder) also provides nested routes, and, like Remix, adopts a isometric
fetch API – see the beta docs on data fetching for details. This means any component moved to the
/app folder no longer uses the prior
The team has been working with
Although you can move to the
/app folder and use the component fetch API, there is a big warning up front:
This new data model is currently being developed by the React and Next.js teams. While you can try it out, it is not yet stable. We'll keep these docs updated to reflect the latest developments.
Clearly this isn't a 'drop the folder into this new /app folder and we're good' feature. It may be advantageous to wait.
Also, you can choose just to upgrade in place to the new version of Next.js and incrementally add layout-driven features.
Of course, switching to a .0 release of anything should be a no-no for an established project, but for people who want to help Vercel improve the platform, and are willing to work with preview alphas for their own research or short-term projects, it's "game on".
Sam Selikoff's conference talk on nested layouts is an excellent preview of layouts and React server and client components in Next 13.
Some of the new components use the template-driven
/app folder, which means you'll have to develop them with React 13 server components to try them out (and Sam's talk above really shows them off).
The main changes:
- A new
Imagecomponent (the old one is still there, with a different package name) – this component has been updated to provide properly sized images in appropriate formats for various devices automatically. It also attempts to prevent cumulative layout shifts during updates. Images are now only loaded when entering the viewport. See the docs for the new image component for details.
- A new
Fontcomponent that inlines fonts completely at build time to prevent external hosting issues. Fonts can be installed in a layout container page, and they are preloaded only when related routes use them.
Additional content is being readied, and you can view the newest Layout-based approaches on their beta docs site.
This industry moves so fast that many features of the other innovators are added by the next version of any given framework. It will be interesting to see how Nuxt and Remix digest these changes, and what other innovations they are incorporating into their own frameworks.
Vercel seems to have a financial edge here, with its hosting platform funding forays into innovation and having acquired well-known developers of key platforms such as Webpack and even frameworks creators such as the creator of Svelte.js. Just take a look at their templates page to see how the hosting platform supports a wide array of solutions, and how their edge functions compete with AWS Lambdas for edge-based computing in the cloud.
I plan on doing a deeper technical dive into Next.js 13 in a future blog post.
As if Halloween changed up the Internet, Shopify just bought Remix.run, giving them a good funding source and more stable path to keeping the framework moving forward. This should help push continuing cross-innovation between teams and to me is good news. Competition is good for innovation.