Skip to content
Back to Blog

Monday, May 11th 2020

Next.js 9.4

Posted by

We are excited today to introduce Next.js 9.4, featuring:

Fast Refresh

Fast Refresh is a new hot reloading experience that gives you instantaneous feedback on edits made to your React components. It is now enabled by default for all projects on Next.js 9.4 or newer.

Hot reloading has existed for a long time but has historically been too fragile to enable by default in your workflow. Because of this, Next.js previously implemented a coarse form of hot reloading that would reset the entire state of your application.

The old hot reloading implementation was not resilient to compilation or runtime errors and would perform a full reload of your application if you made a typo while editing your CSS or JavaScript. This was suboptimal and interrupted your train of thought.

Fast Refresh deeply integrates into React itself (via React Refresh), allowing Next.js to perform predictable precision updates to your React component tree.

This means Next.js will only update code in the file you edited, and only re-render that component, without losing component state. This includes styles (inline, CSS-in-JS, or CSS/Sass Modules), markup, event handlers, and effects (via useEffect).

An editing session featuring compiler and runtime errors (with quick recovery), and edits that preserve state.

As part of this experience, we completely redesigned the error overlay to be more helpful and to make your application resilient to typos or runtime errors. This includes, but is not limited to:

  • Accurate error locations, resolved to the original line and column of your code, before compilation
  • Contextually relevant source code snippets, with the ability click-to-open in your editor
  • Development session resumption after a syntax error is fixed, without losing application state
  • Automatic dismissal of unhandled runtime errors when you fix the error

We would like to thank Dan Abramov for his invaluable contributions and assistance implementing this feature.

Incremental Static Regeneration (beta)

Next.js introduced Static Site Generation methods in 9.3 with a clear goal in mind: we should get the benefits of static (always fast, always online, globally distributed), but with excellent support for dynamic data, which Next.js is known for.

To get the best of both worlds, Next.js supports Incremental Static Generation, updating static content after you have already built your site. For example, in 9.3 we’ve introduced the fallback: true option in getStaticPaths, which allows you to add new pages at runtime.

We recently put together an example showcasing how Next.js can statically pre-render an infinite number of pages this way:

Today, we are also introducing Incremental Static Regeneration (beta), which is a mechanism to update existing pages, by re-rendering them in the background as traffic comes in. Inspired by stale-while-revalidate, this ensures traffic is served uninterrupted, always statically, and the newly built page is pushed only after it's done generating.

pages/blog/[slug].js
export async function getStaticProps() {
  return {
    props: await getDataFromCMS(),
    // we will attempt to re-generate the page:
    // - when a request comes in
    // - at most once every second
    unstable_revalidate: 1,
  };
}

Unlike SSR, Incremental Static Regeneration ensures you retain the benefits of static:

  • No spikes in latency. Pages are served consistently fast.
  • Pages never go offline. If the background page re-generation fails, the old page remains unaltered.
  • Low database and backend load. Pages are re-computed at most once concurrently.

Both incremental features (adding pages and lazily updating them), as well as preview mode, are already fully supported by both next start and the Vercel edge platform out of the box.

Up next, we will be working on a supplemental RFC to address two additional incremental static generation capabilities:

  • Re-generating and invalidating multiple pages at once (like your blog index and a certain blog post)
  • Re-generating by listening to events (like CMS webhooks), ahead of user traffic

CMS Examples

On the heels of our announcement of next-gen static site generation, we wanted to share real-world scenarios of fetching content from Headless CMS APIs and rendering it as Next.js HTML.

We partnered with the creators of some of the best CMS systems in the world: Contentful, DatoCMS, Prismic, Sanity, and TakeShape, with more on the way.

These examples are not only ready to be used and 100% open source and MIT licensed, but they incorporate the best practices available:

DatoCMS achieves impeccable results due to their built-in image optimization support.
DatoCMS achieves impeccable results due to their built-in image optimization support.

DatoCMS achieves impeccable results due to their built-in image optimization support

We also have collaborated with TinaCMS on an exciting new direction for CMS: in-page editing of content. Check out their guide to learn how to implement it for your project.

New Environment Variables Support

A common piece of feedback that we got from companies using Next.js is that it was unclear when an environment variable is inlined into the browser bundle and when it is only available in the Node.js environment.

Today we're announcing two fully backward-compatible features that will help streamline this process.

First, you can now prefix the environment variable with NEXT_PUBLIC_ to expose an environment variable to the browser. When that environment variable is used it will then be inlined into the browser JavaScript bundle.

You no longer have to add a next.config.js and add the env key to expose these variables.

pages/index.js
// The environment variable will be exposed to the browser
console.log('My Application Version', process.env.NEXT_PUBLIC_VERSION);
 
export default function HomePage() {
  return <h1>Hello World</h1>;
}

The second change is that Next.js now supports .env loading by default. Allowing you to easily define development and production environment variables.

You can read more about the .env loading in the Environment Variables documentation.

These new features will simplify using environment variables by following these conventions:

  • Environment variables are only available in the Node.js environment by default
  • Environment variables prefixed with NEXT_PUBLIC_ are exposed to the browser

Improved Built-in Fetch Support

In Next.js 9.1.7 we announced polyfilling of the fetch() API in the browser. Today this polyfilling has been extended to the Node.js environment too.

In practice, you no longer have to use any type of server-side fetch polyfill (for example isomorphic-unfetch or node-fetch) as Next.js will automatically provide fetch() in all environments.

For example, when using getStaticProps, which gets executed using Next.js at build time:

pages/blog.js
export async function getStaticProps() {
  // fetch no longer needs to be imported from isomorphic-unfetch
  const res = await fetch('https://.../posts');
  const posts = await res.json();
 
  return {
    props: {
      posts,
    },
  };
}
 
function Blog({ posts }) {
  // Render posts...
}
 
export default Blog;

Integrated Web Vitals Reporting

Last week the Google Chrome team introduced Core Web Vitals. Core Web Vitals are the quality signals key to delivering great UX on the web, on top of which the famous Lighthouse reports are built.

Keeping track of these metrics is extremely useful if you want your website or web application to be as fast as possible, which is one of the core goals of Next.js.

The Chrome team has released a Core Web Vitals Chrome extension that allows you as a developer to get visual feedback on how your pages are performing.

When building production web applications you also want to know how your site is performing for your visitors and (potential) customers. You might even want to track the improvement or regression of these metrics over time in order to see if your changes have the intended impact on your audience.

In order to aid reporting Core Web Vitals to your analytics service we have introduced, in collaboration with Google, a new method called reportWebVitals which can be exported from pages/_app.js:

pages/_app.js
// Will be called once for every metric that has to be reported.
export function reportWebVitals(metric) {
  // These metrics can be sent to any analytics service
  console.log(metric);
}
 
function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}
 
export default MyApp;

To use this method in combination with your analytics service refer to the "Sending result to Analytics" section of the docs. If you want to learn more about Core Web Vitals you can refer to web.dev/vitals.

Absolute Imports and Aliases

If you’re working on a large project, some of your import statements might suffer from the ../../../ spaghetti:

import Button from '../../../../components/button';

In such cases, instead of relative imports, we might want to use absolute imports. Assuming that the components directory exists at the root, we might want import statements to look like:

import Button from 'components/button';

We're excited to announce that Next.js 9.4 makes setting up absolute imports super simple for both JavaScript and TypeScript projects. All you need to do is to add the baseUrl config to jsconfig.json (JS projects) or tsconfig.json (TS projects).

jsconfig.json / tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "."
  }
}

This will allow absolute imports from . (the root directory). It also integrates with VSCode and other editors, supporting code navigation and other editor features.

Note: If you’ve previously modified your Webpack module alias configuration to enable absolute imports, that configuration can now be removed.

Furthermore, Next.js 9.4 also supports the paths option, which allows you to create custom module aliases. For example, the following allows you to use @/design-system instead of components/design-system:

jsconfig.json / tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/design-system/*": ["components/design-system/*"]
    }
  }
}

You can then use your alias like so:

// Imports 'components/design-system/button'
import Button from '@/design-system/button';

You must specify baseUrl if you specify paths. You can learn more about the paths option in the TypeScript documentation.

Configurable Sass Support

When built-in Sass support was launched in Next.js 9.3 we got the feedback that a subset of users wanted to configure the sass compiler. For example to configure includePaths.

This is now possible by using the sassOptions key in next.config.js:

next.config.js
const path = require('path');
 
module.exports = {
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')],
  },
};

Improved Log Output

We have redesigned the command line output to be more consistent and output less duplicate data like the deployment URL, waiting on the development server to start and more. We've also changed the spacing of the message type to be consistent across messages, meaning they no longer jump from line to line.

Running next dev on versions before 9.4

Running next dev on 9.4

Community

We're excited to see the continued growth in Next.js adoption:

  • We have had over 1066 independent contributors.
  • On GitHub, the project has been starred over 48,000 times.

Join the Next.js community on GitHub Discussions. Discussions is a community space that allows you to connect with other Next.js users and ask questions.

If you are using Next.js feel free to share your project url with the community.

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