Next.js 9.1.7

Next.js 9 was released six (6) months ago, followed by Next.js 9.1 three (3) months ago. These two releases added very powerful new features to Next.js, without increasing our baseline client runtime size.

Since then, we've focused heavily on refining and improving the framework as a whole: 9.1.1, 9.1.2, 9.1.3, 9.1.4, 9.1.5, 9.1.6, and 9.1.7. Let's dive into what these releases have improved!

All of these benefits are non-breaking and fully backwards compatible. All you need to do to update is run:

npm i next@latest react@latest react-dom@latest

In collaboration with the Google Chrome team, all Next.js applications will benefit from a 7.5kB or more size reduction.

Basic applications should see a 3-4% application size reduction, and more advanced applications may see upwards of 6-8% (or more)!

 9.0.x9.1.xdelta
Basic Application68.9kB66.1kB4.1%smaller

These savings are partially attributable to replacing the url package's client-side version with one built atop the URL API.

More size reduction has been accomplished by providing built-in, small polyfills for often-used packages. You can read more about those polyfills here.

Lastly, we've optimized our JSX output which will introduce savings in direct correlation to the amount of JSX in your application.

The CLI's production build output has been redesigned for clarity. Because Next.js is a hybrid application framework, each page may have different characteristics.

The new output classifies each page as one of the following:

  • Server-Side Rendered (Server): the page server-side renders at runtime, meaning it uses getInitialProps or getServerProps (proposal)
  • Automatically Statically Optimized (Static): the page was rendered as static HTML at build time, and will be served as a static file (uses no initial props)
  • Statically Generated Using Computed Data (SSG): the page was generated as static HTML/JSON at build time, and will be served as static files (uses getStaticProps (proposal))

Furthermore, the new output displays the Gzipped size of each page — these sizes exclude files that are shared by all pages (displayed separately).

Each page's size will be colored in accordance with their perceived user experience:

  • Less than 130kB: Green — your application should be performant under most network and device conditions.
  • Between 130kB and 170kB: Yellow — your application is nearing a 5-6 second load time on global baseline device + network conditions.
  • More than 170kB: Red — your application will likely take more than 6 seconds to load on the same conditions.
The New Next.js Production CLI Output

We'd love to hear your feedback about the new build output.

In the near future Next.js will also have size budgets that help you ensure pages are within a certain size bracket.

While examining many users' applications and our examples, we found that most shipped with a similar set of polyfills. In some cases, applications even had duplicate polyfills for the same feature.

To remedy this, we collaborated with the Google Chrome team to build in polyfills for the three most common APIs we observed.

Using differential loading, these polyfills are not loaded for 83% of web traffic globally. This means that the majority of your users will not download the bytes associated with these polyfills—they'll only be downloaded if necessary.

Furthermore, any well-known polyfills that we've now built in will be completely eliminated from your production build. This means you will not pay the price for one of your dependencies that inadvertently import a polyfill for one of these APIs.

The list of built-in APIs and the polyfills they make obsolete are as follows:

You still need to import isomorphic-fetch or isomorphic-unfetch if you're using fetch() on the server.

This change is completely non-breaking, and all polyfills are made with the most spec-compliant versions available. The result is up to 18kB of JavaScript eliminated from your production bundles on modern browsers.

Next.js has optimized its preloading implementation to reduce FCP and overall TTI.

By working around a browser bug, CSS (when used) is now correctly prioritized over JavaScript. This results in a faster First Contentful Paint, resulting in a much faster visually complete website for your end-users.

Additionally, we've optimized our page prefetching to use lower-priority network requests. Furthermore, these requests only happen during browser idle-time, resulting in a quicker time-to-interactive. This is because the browser will prioritize making your application interactive over optimistic prefetching.

FCP/TTI Before and After Optimizations

Next.js has an advanced, highly optimized compilation pipeline that allows you to use the latest JavaScript features. Recent optimizations we have introduced directly contributed to the 3-8% reduction in application size.

These JavaScript features can be leveraged without worrying about browser compatibility, as we automatically compile your code to support all browsers (excluding end-of-life versions). This includes ES6+ features, such as async/await (ES2017), Object Rest/Spread Properties (ES2018), Dynamic import() (ES2020), and more!

In this release, we're happy to announce support for Optional Chaining (Stage 4) and Nullish Coalescing (Stage 4).

function Page(props) {
  return (
    <p>{props?.deeply?.nested?.value}</p>
    /* ⬆ If deeply.nested.value is not available it won't render */
  )
}

export default Page

Optional chaining operator (?.)

function Page(props) {
  return (
    <p>{props.something ?? 'Default value'}</p>
    /* ⬆ results in "Default value" */
  )
}

export default Page

Nullish coalescing operator (??)

In the future, we plan to output even more optimized bundles via automatic module / nomodule builds.

Next.js' next export command now works with Vercel’s Zero Configuration out-of-the-box. Prior to this change, users who leveraged next export were required to create a custom now.json.

Leveraging Next.js' export-mode on Vercel is as simple as having the following build script in package.json:

{
  "scripts": {
    "build": "next build && next export"
  }
}

Then, you can deploy your Next.js application to Vercel with only a single command.
If you have not yet installed Now, you can do so by installing Vercel CLI.

now

The complete Next.js runtime is now Strict Mode-compliant. This included updates to Next.js' head manager (<Head>), next/dynamic, and other core features. This means the runtimes now leverage hooks or have eliminated deprecated lifecycles, and are using React's new Context API.

We've also added a convenient opt-in option for you to enable Strict Mode for your application.

To do so, configure the following option in your next.config.js:

// next.config.js
module.exports = {
  reactStrictMode: true
}

If you or your team are not ready to use Strict Mode in your entire application, that's OK! You can incrementally migrate on a page-by-page basis using <React.StrictMode>.

While not required, Strict Mode will unlock a lot of optimizations in the future. Because of this, we suggest you look into it sooner rather than later!

In close collaboration with the React Core Team, we're now testing Next.js against React's next channel every 12 hours.

These tests help ensure we're prepared and compatible with the future releases of React. Compatibility is something Next.js takes very seriously, and we're committed to the long-term API stability of Next.js.

This process has been documented by the React Core Team in hopes other projects in the React ecosystem follow suit.

We are excited about the upcoming changes that will improve size and performance across all Next.js applications.

Furthermore, the Next.js community is still expanding:

  • We have had over 865 independent contributors.
  • On GitHub, the project has been starred over 43,700 times.
  • The examples directory has over 220 examples.

The Next.js community now has over 13,600 members. Join us!

We are thankful to our community and all the external feedback and contributions that helped shape this release.