New features in Next.js 11

Written by Kapeel Kokane ✏️

At the 2021 Next.js Conf on June 15, developers from around the world joined to witness the launch of Next.js 11, the latest release from the Vercel team. The updates and new features included in Next.js 11 have offered significant improvements to an already popular library.

In this article, we’ll take an in-depth look at some of these updates, which have impacted both the user and developer experiences. Let's get started!

Conformance

At its core, conformance is a set of principles or coding guidelines that takes some of the decision-making responsibility away from the developer. By setting defaults and providing guidelines, it is easier to achieve a desired result and prevent common mistakes.

According to the Next.js team, "conformance is a system that provides carefully crafted solutions and rules to support optimal loading and Core Web Vitals".

The new conformance principles in Next.js 11 can be broken down into three areas:

1. Strong defaults

The framework must have certain design patterns established in its core that make it difficult for the developer to do things incorrectly.

2. Actionable rules

Despite having strong defaults in place, there will be occasions where the onus falls on the developer to select between two potential paths. A set of actionable rules will make it easier for the application to adhere to strong performance standards while still allowing a sufficient level of customization.

3. Authoring time

Authoring time gives importance to performance during a feature’s development cycle instead of after production. Performance must be considered before code commit instead of being treated as an analytics-based metric after the product release.

One of the easiest ways to enforce the authoring time principle is through linting rules. Therefore, Next.js 11 supports ESLint out of the box.

To get the benefits of these features, you have to upgrade to the latest version of Next.js by running the following code:

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

Enable linting by running the code below:

npx next lint

Once we upgrade our version and enable ESLint, we’ll begin to receive warnings that nudge us in the direction of industry best practice, helping our apps adhere to conformance guidelines.

Script optimization

Many websites include third-party scripts to enable analytics and advertisements.

The order in which scripts are loaded has a huge impact on page performance, particularly when dealing with several external scripts on a webpage. If not managed appropriately, scripts can severely degrade the user experience.

Next.js has introduced a Script Component with a strategy property that handles a lot of these issues.

Let’s test it out! One noticeable change is that we no longer have to wrap the native HTML script tag in the next/head tag:

import Head from 'next/head'
function Home() {
 return (
    <>
      <Head>
        <script async src="https://polyfill.io/v3/polyfill.min.js?features=WebAnimations" />
      </Head>
    </>
  )
}

Instead, we can use the native HTML script tag directly, as seen below:

import Script from 'next/script'
function Home() {
  return (
    <>
      <Script src="https://polyfill.io/v3/polyfill.min.js?features=WebAnimations" />
    </>
  )
}

In this example, we are advised to load our polyfill using the beforeInteractive strategy. Let’s change strategies to see how it impacts loading the scripts!

beforeInteractive

Scripts are injected into the HTML at server side and run on the browser before the bundled JavaScript can run. Using the code block below, we see that the network call to fetch the polyfill is made before everything else in the network tab:

<Script src="https://polyfill.io/v3/polyfill.min.js?features=WebAnimations" 
`strategy="beforeInteractive" />

afterInteractive

If we change our strategy to afterInteractive, the script would execute after the page becomes interactive. The network request is towards the bottom of the page in the network tab, which prioritizes more important tasks.

lazyOnload

Changing the strategy to lazyOnload tells Next.js to load the script during idle time. The network request to fetch the polyfill moves further down to the bottom of the page; there are no other lazy loaded scripts, as seen in the next screenshot.

onLoad prop

In addition to the customizations above, if we want to execute some code after a script is loaded, we can use the onLoad prop for the script tag. The onLoad prop ensures that the script above has loaded, allowing the function to use the script's features and variables without crashing:

<Script
  id="my-script"
src="https://polyfill.io/v3/polyfill.min.js?features=WebAnimations"
  onLoad={() => {
    // this executes after the script is loaded
  }}
/>

Image improvements

Next.js 11 includes enhancements to the next/image component like reducing layout shifts, which provides a smoother experience for the end user.

Size detection for static images

Previously, to render images using the Image component, the height and width props were mandatory. These props allowed Next.js to identify the size of the image and render a placeholder, preventing layout shifts and disorganized user interfaces:

<Image
  alt="Fixing"
  src="/fixing.png"
  layout="intrinsic"
  width={700}
  height={475}
/>

Next.js 11 provides support for the src prop, which can be applied using the import keyword. You don’t need to specify the height and width props separately if you import the source in this manner:

import source from '../public/fixing.png'
<Image
  alt="Fixing"
  src={source}
  layout="intrinsic"
/>

Image placeholders

In Next.js 11, the next/image component supports a new placeholder prop that sets value to blur on slower connections. The next/image component will display a blurred, low resolution image while the original image is loading:

<Image
  alt="Fixing"
  src={source}
  layout="intrinsic"
  placeholder="blur"
/>

The blurred image will be shown for two to three seconds before the original image finally loads.

Additionally, Next.js 11 provides an option to supply a custom placeholder through the Image tag, which can be shown using the blurDataURL prop. The value supplied to this prop can be generated using an application like blurha.sh.

Webpack 5 default support

Webpack 5 support was announced in version 10.2 for all Next.js projects without a custom webpack configuration in their next.config.js file. A custom webpack configuration looks like the code below:

module.exports = {
  webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
    return config; // return the modified config
  },
}

From version 11 onwards, webpack 5 is the default build tool for all Next.js applications, irrespective of the custom config. All of the following optimizations that come with webpack 5 will be available to newly built projects.

Improved disk caching

We know that we can trigger a build using the command next build. But what if little has changed between the two successive builds that we trigger for the project?

Webpack 5 allows for conditional recompilation of only the files that have been changed. Performance is improved because we don’t redundantly process chunks that have not been altered.

Improved fast refresh

With webpack 5 in place, Next.js 11 identifies fast refresh as a special task and executes it at a higher priority, leading to a faster refresh every time any code change is saved.

Long-term asset caching

With webpack 5 in place, the build process for the build command is deterministic. Hashes generated upon subsequent builds do not change if the code segments have not changed, meaning files hashed in the browser can be reused over a longer time.

Improved tree shaking

Webpack 5 provides the capability to tree shake commonJS modules, removing unused code from the bundle.

Migration from Create React App

Due to requests from the community, the Vercel team has launched the @next/codemod tool, which supports compatibility between React and Next.js projects.

We can run the tool, supply it a project generated using the Create React App script, and convert it to a Next.js project. Let's try it out!

First, create a React app using the command:

npx create-react-app cra-demo

Now, that we’ve initialized a new React project, we can run our project using the command:

npm run start

You’ll see the familiar React screen:

npx @next/codemod cra-to-next cra-demo

We can see that the script makes several changes to the repository to port it to Next.js. These changes include:

  • Changes to the scripts in package.json
  • Addition of the pages folder, which is a main feature of a Next.js repo
  • Changes to how CSS is imported by creating an _app.js file
  • Creation of a next.config.js file and population of it

Babel optimization

Next.js 11 features a brand new implementation of the Babel loader for webpack, which includes an in-memory config caching layer that further reduces the startup time from improvements made in versions 10.1 and 10.2.

Next.js Live

The team at Vercel has used several next-gen frontend technologies like serviceWorker, WebAssembly, and ES modules to provide a collaborative environment right inside the browser. Using the Next.js Live feature, developers and designers can collaborate simply by sharing a URL. The Live feature is currently running under early access.

Conclusion

It is clear that these upgrades make up one of the most prominent Next.js releases ever!

There are changes made to the core that reduce startup times, like the Babel optimization, and conformance suggestions that nudge the developer towards a proven solution. Other improvements are to loading images and scripts, making the user experience seamless. Additionally, we now have the ability for improved collaboration using the Live feature.

For these reasons and more, the Next.js 11 version looks promising and worthy of an upgrade. Give it a try and let us know what you think in the comments!

LogRocket: Full visibility into production Next.js apps

Debugging Next applications can be difficult, especially when users experience issues that are difficult to reproduce. If you’re interested in monitoring and tracking state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your Next.js apps — start monitoring for free.

19