After 26 canary releases and 3.4 million downloads, we are proud to introduce the production-ready Next.js 7, featuring:
- DX improvements: 57% faster bootup, 42% faster re-compilation
- Better error reporting with react-error-overlay
- Upgraded compilation pipeline: Webpack 4 and Babel 7
- Standardized Dynamic Imports
- Static CDN support
- Smaller initial HTML payload
- React Context with SSR between App and Pages
Finally, we are excited to be sharing this news on the all-new Nextjs.org
DX Improvements
One of Next.js's primary goals is to provide the best production performance with the best possible developer experience. This release brings about many significant improvements to the build and debug pipelines
Compilation Speed
Thanks to webpack 4, Babel 7 and many improvements and optimizations on our codebase, Next.js now boots up to 57% faster during development.
Thanks to our new incremental compilation cache, changes you make to the code will now build 40% faster.
These are some example figures we have collected:
6.0 | 7.0 | delta | |
---|---|---|---|
Bootup time (basic application) | 1947ms | 835ms | 57%faster |
Code change (basic application) | 304ms | 178ms | 42%faster |
As a bonus, when developing and building you will now see better realtime feedback thanks to webpackbar:
Better error reporting with React Error Overlay
Rendering accurate and help errors is critical to a great development and debugging experience. Until now, we would render the error message and its stack trace. Moving forward, we make use of react-error-overlay
to enrich the stack trace with:
- Accurate error locations for both server and client errors
- Highlights of the source to provide context
- A full rich stack trace
This is a comparison of the before and after of our errors:
As a bonus, react-error-overlay
makes it easy to open your text editor by just clicking on a specific code block.
Webpack 4
Since its very first release Next.js has been powered by webpack for bundling your code and re-using the rich ecosystem of plugins and extensions. We're excited to announce Next.js is now powered by the latest webpack 4, which comes with numerous improvements and bugfixes.
Among these we get:
- Support for
.mjs
source files - Code splitting improvements
- Better tree-shaking (removal of unused code) support
Another new feature is WebAssembly support, Next.js can even server-render WebAssembly, here is an example.
Note: this upgrade is fully backwards-compatible. However, if you are using custom webpack loaders or plugins via next.config.js, you might have to upgrade them.
CSS Imports
With webpack 4, a new way of extracting CSS from bundles was introduced, called mini-extract-css-plugin.
@zeit/next-css
, @zeit/next-less
, @zeit/next-sass
, and @zeit/next-stylus
are now powered by mini-extract-css-plugin
.
The new version of these Next.js plugins solves 20 existing issues related to CSS imports; As an example, importing CSS in dynamic import()
s is now supported:
// components/my-dynamic-component.js import './my-dynamic-component.css' export default function MyDynamicComponent() { return <h1>My dynamic component</h1> }
// pages/index.js import dynamic from 'next/dynamic' const MyDynamicComponent = dynamic(import('../components/my-dynamic-component')) export default function Index() { return () { <div> <MyDynamicComponent/> </div> } }
A major improvement is that you are no longer required to add the following to pages/_document.js
:
<link rel="stylesheet" href="/_next/static/style.css" />
Instead, Next.js automatically injects the CSS file. In production, Next.js also automatically adds a content hash to the CSS URL, so that if there are changes, to ensure that your end-users never get stale versions of the file and have the ability to introduce immutable permanent caching.
In short, all you have to do to support importing .css
files in your Next.js project is to just register the withCSS plugin in your next.config.js
:
const withCSS = require('@zeit/next-css') module.exports = withCSS({ /* my next config */ })
Standardized Dynamic Imports
Next.js has had support for dynamic imports through next/dynamic
since version 3.
As early adopters of this technology, we had to write our own solution for handling import()
.
As a consequence, Next.js was beginning to diverge from the support that webpack later introduced for it and some features were missing.
Because of this Next.js did not support a few import()
features webpack has introduced since.
For example, naming and bundling certain files together manually was not possible:
import(/* webpackChunkName: 'my-chunk' */ '../lib/my-library')
Another example is using import()
without being wrapped in the next/dynamic
module.
Starting with Next.js 7 we no longer touch the default import()
behavior. This means you get full import() support out of the box.
This change is fully backwards-compatible as well. Making use of a dynamic component remains as simple as:
import dynamic from 'next/dynamic' const MyComponent = dynamic(import('../components/my-component')) export default function Index() { return ( <div> <MyComponent /> </div> ) }
What this example does is create a new JavaScript file for my-component
and only load it when <MyComponent />
is rendered.
Most importantly, if it is not rendered, the <script>
tag is not included in the initial HTML document payload.
To further simplify our codebase and make use of the excellent React ecosystem, in Next.js 7 next/dynamic
was re-written to make use of react-loadable
behind the scenes (with some minor modifications). This also introduces two great new features for dynamic components:
- Timeouts using the
timeout
option onnext/dynamic
- A loading component delay, using the
delay
option onnext/dynamic
. This delay allows yourloading
component to wait x time before rendering the loading state, for example, if the import is very fast.
Babel 7
Next.js 6 introduced Babel 7 while it was still in beta. Since then the stable version of Babel 7 has been released, and Next.js 7 now using this version.
For a full list of changes, you can refer to Babel its release notes.
Some of the main features are:
- Typescript support, for Next.js you can use
@zeit/next-typescript
- Fragment syntax
<>
support babel.config.js
supportoverrides
property to apply presets/plugins only to a subset of files or directories
If you do not have a custom Babel configuration in your Next.js project, there are no breaking changes.
If you do however have a custom Babel configuration, you have to upgrade the respective custom plugins/presets to their latest version.
In case you are upgrading from a version below Next.js 6 you can run the excellent babel-upgrade
tool.
In addition to upgrading to Babel 7, the Next.js Babel preset (next/babel
) now defaults to setting the modules
option to commonjs
when NODE_ENV
is set to test
.
This configuration option was often the only reason for creating a custom .babelrc
in a Next.js project:
{ "env": { "development": { "presets": ["next/babel"] }, "production": { "presets": ["next/babel"] }, "test": { "presets": [["next/babel", { "preset-env": { "modules": "commonjs" } }]] } } }
With Next.js 7 this becomes:
{ "presets": ["next/babel"] }
At this point, the .babelrc
can be removed, as Next.js will then automatically use next/babel
when there is no Babel configuration.
Smaller Initial HTML Payload
As Next.js pre-renders HTML, it wraps pages into a default structure with <html>
, <head>
, <body>
and the JavaScript files needed to render the page.
This initial payload was previously around 1.62kB. With Next.js 7 we've optimized the initial HTML payload, it is now 1.5kB, a 7.4% reduction, making your pages leaner.
6.0 | 7.0 | delta | |
---|---|---|---|
Document size (server rendered) | 1.62kb | 1.50kb | 7.4%smaller |
The main ways we have reduced size are:
- The
__next-error
div is removed - The inline scripts are minified, in a future release they will be completely removed
- Compiled away unused
__NEXT_DATA__
properties when they are not used, for example, thenextExport
andassetPrefix
properties.
Static CDN Support
In Next.js 5 we introduced assetPrefix
support, a way to make Next.js automatically load assets from a certain location, usually a CDN. This option works great if your CDN supports proxying, you request an URL like
https://cdn.example.com/_next/static/<buildid>/pages/index.js
Typically, the CDN checks if it has the file in its cache, or otherwise requests it directly from the origin.
Proxying assets is precisely how the Edge Network works.
However, some solutions require pre-uploading a directory directly into the CDN. The problem in doing this is that Next.js its URL structure did not match the folder structure inside the .next
folder. For example our earlier example
https://cdn.example.com/_next/static/<buildid>/pages/index.js // mapped to: .next/page/index.js
With Next.js 7 we have changed the directory structure of .next
to match the url structure:
https://cdn.example.com/_next/static/<buildid>/pages/index.js // mapped to: .next/static/<buildid>/pages/index.js
While we do recommend using the proxying type of CDN, this new structure allows users of a different type of CDN to upload the .next
directory to their CDN.
Styled JSX v3
We are excited to introduce styled-jsx 3, the by default included CSS-in-JS solution in Next.js is now ready for React Suspense.
One thing that was often unclear was how to style a child component if that component is not part of the current component scope, for example, if you included a child component that needed specific styles only when used inside the parent component:
const ChildComponent = () => ( <div> <p>some text</p> </div> ) export default function Index() { return ( <div> <ChildComponent /> <style jsx>{` p { color: black; } `}</style> </div> ) }
The above code tries to select the p
tag does not work because styled-jsx styles are scoped to the current component, they do not leak into child components. One way to get around this was using the :global
method, removing the prefix from the p
tag. However, this introduces a new issue, which is that styles do leak across the page.
In styled-jsx 3 this issue has been solved by introducing a new API, css.resolve
, which will generate the className
and <style>
tags (the styles
property) for the given styled-jsx string:
import css from 'styled-jsx/css' const ChildComponent = ({ className }) => ( <div> <p className={className}>some text</p> </div> ) const { className, styles } = css.resolve` p { color: black; } ` export default function Index() { return ( <div> <ChildComponent className={className} /> {styles} </div> ) }
This new API allows for transparently passing through custom styling to child components.
Since this is a major release for styled-jsx, there is one breaking change that improves bundle sizes if you are using styles-jsx/css
.
In styled-jsx 2 we would generate a "scoped" and "global" version of external styles, even when only the "scoped" version was used we would still include the "global" version of those external styles.
With styled-jsx 3 global styles have to be tagged with css.global
instead of css
, so that styled-jsx can optimize bundle size.
For all changes, please refer to the release notes.
React Context with SSR between App and Pages
Starting from Next.js 7 we now support the new React context API between pages/_app.js
and page components.
Previously it was not possible to use React context in between pages on the server side. The reason for this was that webpack keeps an internal module cache instead of using require.cache, we've written a custom webpack plugin that changes this behavior to share module instances between pages.
In doing so we not only allow usage of the new React context, but also reduce Next.js's memory footprint when sharing code between pages.
6.0 | 7.0 | delta | |
---|---|---|---|
Memory usage | 57.5MB | 48.1MB | -16%memory |
nextjs.org
Together with the Next.js 7 release, we are launching a completely redesigned nextjs.org.
Blog
The blog post you are currently reading is already part of the new blog section on nextjs.org. This blog will be the new home for communication related to Next.js, for example, new version announcements.
Get Inspired
As the amount of apps using Next.js is continuously growing, we needed a way to show all these beautiful apps in one overview. Meet the new /showcase
page:
This new showcase allows us to add new apps built with Next.js continuously.
We invite you to visit /showcase
to get inspired, or submit your app that uses Next.js!
Community
Ever since it's first release Next.js has been used in everything from fortune 500 companies to personal blogs. We're very excited to see the growth in Next.js adoption.
- Currently, there are over 12,500 publicly indexed domains using Next.js.
- We've had over 500 contributors landing at least 1 commit.
- On GitHub, the project has been starred over 29,000 times.
- Almost 2200 pull requests were submitted since the first release.
The Next.js community has nearly 2000 members. Join us!