Thursday, December 22nd 2022
Next.js 13.1
Posted byNext.js 13.1 includes improvements to both the pages/
(stable) and app/
(beta) directories:
app
Directory (Beta) Improvements: Improved reliability and performance.- Built-in Module Transpilation: Bringing
next-transpile-modules
capabilities into core. - Edge Runtime (Stable): A light Node.js runtime for the Edge.
- Turbopack Updates: Support for Tailwind CSS,
next/image
,@next/font
, and more. - Middleware Improvements: Return responses and set request headers.
- SWC Import Resolution: For smaller JavaScript bundles when using barrel files.
- Memory usage improvements, new templates, and more!
Update today by running:
npm i next@latest react@latest react-dom@latest eslint-config-next@latest
Improved reliability and support for app
directory
In Next.js 13, we announced the new app
directory (beta). This new routing and data fetching system can be incrementally adopted alongside your existing pages
directory.
The app
directory provides many benefits, including enhanced layouts, co-location of components, tests, and styles, component-level data fetching, and more. Thanks to your feedback and early testing, we've made several improvements to the reliability of the app
directory:
- No Layout Divs: Previously, the
app
directory added additional<div>
elements to scroll layouts into view when navigating. With 13.1, these extra elements are no longer created. The scrolling behavior is preserved. - TypeScript Plugin: We've built a new TypeScript plugin that provides suggestions for page and layout configuration options, brings documentation directly into your IDE, and provides helpful usage hints around Server and Client Components (such as preventing the use of
useState
in Server Components). Learn more. - Reliability Improvements: We've patched numerous bugs, including improved CSS modules support, correctly de-duplicating
cache()
andfetch()
for layouts and pages, memory leaks, and more. - Less Client-Side JavaScript: The
app
directory now includes9.3kB
less client-side JavaScript than thepages
directory. This baseline doesn't increase whether you add 1 or 1000 Server Components to your application. The React runtime is temporarily slightly larger, the increase is caused by the React Server Components runtime, which handles mechanics that Next.js previously handled. We are working to reduce this further.
pages/ | app/ | delta | |
---|---|---|---|
Total First Load JS | Baseline | -9.3kB | 12.1% smaller |
Next.js Runtime | Baseline | -12kB | 56.8% smaller |
React Runtime | Baseline | +2.7kB | 5.2% larger |
We're excited about continuing to make progress on the stability of the app
directory. The beta documentation for the app
directory has had hundreds of updates based on your feedback.
Built-in module transpilation (stable)
You can now mark dependencies from local packages (like monorepos) or from external dependencies (node_modules
) to be transpiled and bundled. This built-in support replaces the popular next-transpile-modules
package.
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ['@acme/ui', 'lodash-es'],
};
module.exports = nextConfig;
We are thankful to Pierre de la Martinière (@martpie) for their work on this package and their assistance in helping ensure the built-in support met the community's needs.
Import resolution for smaller bundles
Many popular npm packages make use of "barrel files" to provide a single file that re-exports other modules. For example:
export { default as Button } from './dist/Button';
export { default as Slider } from './dist/Slider';
export { default as Dropdown } from './dist/Dropdown';
This allows consumers of the package to use named exports in a single line:
import { Button, Slider, Dropdown } from '@acme/ui';
While bundlers understand these barrel files and can remove unused re-exports (called "dead code elimination"), this process involves parsing/compiling all re-exported files. In case of published libraries some npm packages ship barrel files that have thousands of modules re-exported, which slows down compile times. These libraries recommended babel-plugin-transform-imports
to avoid this issue, but for those using SWC, there was no previous support. We've added a new SWC transform built into Next.js called modularizeImports
.
This new setting enables the SWC transform which changes your import statements based on a defined pattern. For example, the above code for using three components would be automatically converted to use direct imports, without the developer needing to write this code manually:
// Before (with barrel file)
import { Button, Slider, Dropdown } from '@acme/ui';
// After (with modularized imports from plugin)
import Button from '@acme/ui/dist/Button';
import Slider from '@acme/ui/dist/Slider';
import Dropdown from '@acme/ui/dist/Dropdown';
This transformation is possible with the modularizeImports
option in next.config.js
:
module.exports = {
modularizeImports: {
'@acme/ui': {
transform: '@acme/ui/dist/{{member}}',
},
},
};
Leveraging this transform with @mui/icons-material
or lodash
allows skipping compilation of unused files. Learn more.
View a demo to see this in action.
A light Node.js runtime for the edge, now stable for API routes
The Edge Runtime inside Next.js uses a strict subset of Node.js APIs (like Request
, Response
, and more) which are compatible with Edge computing platforms like Vercel or when self-hosting. These APIs run everywhere, including in the browser, allowing developers to learn them once and write everywhere.
// "experimental-" prefix is no longer needed
export const config = {
runtime: 'edge',
};
export default function handler(req: Request) {
return new Response('Hello World');
}
Next.js Middleware already uses this light edge runtime by default for better performance. As Middleware can run before every request in your application, having a lightweight runtime is critical to ensure low latency. In Next.js 12.2, we added the ability to optionally use this runtime for API Routes as well.
With 13.1, the Edge Runtime inside Next.js is now stable for API routes. When self-hosted, Middleware and API Routes using the Edge Runtime will run as a single-region workload by default as part of next start
. On Vercel, Next.js Middleware and API Routes are deployed globally using Vercel Edge Functions for the lowest possible latency. Vercel Edge Functions are also now generally available.
Turbopack improvements
After releasing the Turbopack alpha with Next.js 13, we've been focused on improving reliability, adding support for the most requested features, and defining plans for plugins and usage in other frameworks.
Since Next.js 13.0.0, Turbopack:
- Supports PostCSS, including Tailwind CSS
- Supports
next/image
- Supports
@next/font
(Google Fonts) - Supports loading CSS from dynamic
import()
statements - Supports CSS source maps (thank you
@ahabhgk
for their contribution) - Improved error handling in
next dev
error overlay - Improved memory usage
- Improved CSS modules support
- Improved chunking algorithm for HMR updates
- Improved reliability for HMR source maps
We are thankful to Evan You and the Vite community for their feedback and contributions to ensure the Turbopack benchmarks are as accurate as possible. We've worked together with the Vite team to validate the latest Turbopack benchmarks and make numerous improvements to our testing methodology.
As a result of this collaboration, we now use a more accurate metric which includes time spent in React's update mechanism. We were able to improve React Fast Refresh time by 30ms in Turbopack as well as Next.js 13.1 on webpack. We've also added a new benchmark for using Vite with SWC, which shows improved performance compared to using the default Vite with Babel. View the updated benchmarks or read about the testing methodology.
Try out the Turbopack alpha version today in Next.js 13 with next dev --turbo
. If you have any feedback let us know on the GitHub Discussion.
Next.js advanced Middleware
Thanks to your feedback, we're making Next.js Middleware more powerful than ever. With 13.1, you can now return responses from Middleware, as well as set headers on the request.
These API improvements give you powerful new flexibility to customize every part of the Next.js routing lifecycle. The experimental.allowMiddlewareResponseBody
configuration option inside next.config.js
is no longer required.
You can now more easily set headers on the request, as well as respond directly without having to rewrite
or redirect
:
import { NextResponse } from 'next/server';
export function middleware(request: Request) {
// Check if a user has access...
if (!isAuthorized(request)) {
return NextResponse.json({ message: 'Unauthorized' });
}
// Add a new header, this will change the incoming request headers
// that you can read in getServerSideProps and API routes
const requestHeaders = new Headers(request.headers);
requestHeaders.set('x-version', '13.1');
return NextResponse.next({
request: {
// Apply new request headers
headers: requestHeaders,
},
});
}
Learn more about Next.js advanced Middleware.
Other improvements
@next/font
now supports adding multiple font weights and styles in the same font declaration. Learn more.next/dynamic
now uses React primitiveslazy()
and<Suspense>
. The previoussuspense
option is no longer required. With these changes,next/dynamic
is now compatible with theapp
directory.create-next-app
has been updated with a new design, now including@next/font
by default for automatic self-hosting of fonts with zero layout shift. Try it out withnpx create-next-app@latest
or deploy the template.- We've made numerous improvements to the App Directory Playground, which showcases some of the latest features and conventions of the
app
directory (beta) in Next.js 13. Deploy your own. - We've created a high-performance image gallery template, which includes image placeholders, lazy loading, automatic optimization, keyboard support, and more. Deploy your own.
- We've created a resource for understanding how to migrate a large, open-source React and Express.js application to Next.js, including a detailed walkthrough and links back to specific commits.
Community
Next.js is the result of the combined work of over 2,400 individual developers, industry partners like Google and Meta, and our core team at Vercel. With over 3.6 million npm downloads per week and 97,900+ GitHub stars, Next.js is one of the most popular ways of building the Web.
Join the community on GitHub Discussions, Reddit, and Discord.
This release was brought to you by:
- The Next.js team: Balazs, Hannes, Jan, Jiachi, Jimmy, JJ, Josh, Sebastian, Shu, Steven, Tim, and Wyatt.
- The Turbopack team: Alex, Donny, Justin, Leah, LongYinan, Maia, OJ, Tobias, and Will.
And the contributions of: @aarnadlr, @aaronbrown-vercel, @aaronjy, @abayomi185, @ademilter, @adictonator, @adilansari, @adtc, @alantoa, @aleksa-codes, @alfred-mountfield, @alpha-xek, @andarist, @andykenward, @anujssstw, @artdevgame, @artechventure, @arturbien, @aziyatali, @bennettdams, @bertho-zero, @blue-devil1134, @bot08, @brkalow, @brvnonascimento, @chanceaclark, @chibicode, @chrisipanaque, @chunsch, @colinking, @craigwheeler, @ctjlewis, @cvolant, @danmindru, @davidnx, @delbaoliveira, @devvspaces, @dtinth, @ducanhgh, @duncanogle, @ethomson, @fantaasm, @feugy, @fomichroman, @gruz0, @haschikeks, @hughlilly, @idoob, @iiegor, @imranbarbhuiya, @ingovals, @inokawa, @ishaqibrahimbot, @ismaelrumzan, @jakemstar, @janicklas-ralph, @jaredpalmer, @jaykch, @jimcresswell, @joliss, @josephcsoti, @joshuaslate, @joulev, @jueungrace, @juliusmarminge, @karlhorky, @kikobeats, @kleintorres, @koenpunt, @koltong, @kosai106, @labyrinthitis, @lachlanjc, @laityned, @leerob, @leoortizz, @lorenzobloedow, @lucasassisrosa, @m7yue, @manovotny, @marcus-rise, @matthew-heath, @mattpr, @maxleiter, @maxproske, @meenie, @mmaaaaz, @mnajdova, @moetazaneta, @mrkldshv, @nathanhammond, @nekochantaiwan, @nfinished, @niedziolkamichal, @nocell, @notrab, @nuta, @nutlope, @obusk, @orionmiz, @peraltafederico, @reshmi-sriram, @reyrodrigez, @rightones, @rishabhpoddar, @saseungmin, @serkanbektas, @sferadev, @silvioprog, @sivtu, @soonoo, @sqve, @steven-tey, @sukkaw, @superbahbi, @teobler, @theevilhead, @thomasballinger, @timeyoutakeit, @valentinh, @ws-jm, @wxh06, @yasath, @yutsuten, and @zekicaneksi.