Engineering

Upgrading to Next.js version 13 with Turbopack

Next.js, a React framework, released version 13 in October 2022. We were maintaining a web application built with Next.js version 12, so we went ahead and upgraded. During the upgrade, we encountered several issues which we would like to share here.

We first started with the [.inline-code]next.config.js[.inline-code] configuration file. This file is created for the custom advanced configuration of Next.js. It is located in the root of your project directory (next to [.inline-code]package.json[.inline-code]).

In Next.js 12, our [.inline-code]next.config.js[.inline-code] file looks like this:

  
  // next.config.js

  const { withSentryConfig } = require('@sentry/nextjs');

  const moduleExports = {
    images: {
      domains: [
        "res.cloudinary.com",
        ....
      ],
    },
    env: {
      postsPerPage: 6,
    },
    swcMinify: true,
  };

  const sentryWebpackPluginOptions = {
    silent: true, // Suppresses all logs
  };

  module.exports = withSentryConfig(moduleExports, sentryWebpackPluginOptions);
  
 

In version 13, Next.js’ SWC compiler is used for minification by default. It is claimed to be 7x faster than Terser (used by default in 12). So we no longer had to state [.inline-code]swcMinify: true[.inline-code] in [.inline-code]next.config.js[.inline-code] in order to use SWC. But if Terser is still needed for any reason, it can be configured as below:

  
  swcMinify: false,
  
 

Next, we tried out Turbopack, which is a new JavaScript bundler and the successor to Webpack. It is in alpha release and can be enabled in development mode. It is claimed that on large applications, Turbopack updates 10x faster than Vite and 700x faster than Webpack. To enable Turbopack, we started with the following change:

  
  // package.json

  "scripts": {
    "dev": "next dev --turbo",
    ....
  }
  
 

After starting up our development server, we encountered the below error:

  
  $ next dev --turbo
  info  - Loaded env from /var/app/.env
  >>> TURBOPACK (alpha)
  …..
  Warning: You are using configuration that may require additional
  setup with Turbopack. If you already made these changes please
  ignore this warning.

  - PostCSS detected (postcss.config.js)
    PostCSS is not yet supported by Next.js v13 with Turbopack.
    To use with Turbopack, see: https://nextjs.link/turbopack-postcss

  - Tailwind detected (tailwind.config.js)
    Tailwind is not yet supported by Next.js v13 with Turbopack.
    To use with Turbopack, see: https://nextjs.link/turbopack-tailwind

  Error: You are using configuration and/or tools that are not yet
  supported by Next.js v13 with Turbopack:
  
 

Turbopack doesn’t currently support Tailwind CSS out of the box. But we had previously configured our application to use Tailwind CSS and PostCSS as below:

  
  // package.json

  "devDependencies": {
    ....
    "autoprefixer": "^10.4.13",
    "postcss": "^8.4.19",
    "tailwindcss": "^3.2.4"
  }
  
  
  // styles/globals.css

  @tailwind base;
  @tailwind components;
  @tailwind utilities;
  
  
  // postcss.config.js

  module.exports = {
    plugins: {
      tailwindcss: {},
      autoprefixer: {},
    },
  }

  // tailwind.config.js

  module.exports = {
    content: ['./pages/**/*.{js,ts,jsx,tsx}', './components/**/*.{js,ts,jsx,tsx}'],
    theme: { .... },
    plugins: [ …. ],
  }
  
  // pages/_app.js

  import '../styles/globals.css';
  

However, we found a workaround that allows Turbopack to work with Tailwind CSS.

We use [.inline-code]yarn[.inline-code] package manager to install the npm package called [.inline-code]concurrently[.inline-code]:

  
  yarn add --dev concurrently 
  
 

This adds [.inline-code]concurrently[.inline-code] as part of [.inline-code]devDependencies[.inline-code] in [.inline-code]package.json[.inline-code]:

  
  // package.json

  "devDependencies": {
    ....
    "concurrently": "^7.6.0",
  }
  
 

Then we moved the [.inline-code]dev[.inline-code] and [.inline-code]build[.inline-code] commands to [.inline-code]scripts[.inline-code], and imported the compiled CSS output file.

  
  // package.json

  "scripts": {
     "dev": "concurrently \"next dev --turbo\" \"tailwindcss --input ./styles/globals.css --output ./styles/output.css --watch\"",
     "build": "tailwindcss ./styles/globals.css --output ./styles/output.css && next build",
  }
  
  
  // pages/_app.js

  import '../styles/output.css';
  
 

[.inline-code]concurrently[.inline-code] allows us to run Tailwind CLI in parallel to compile our CSS [.inline-code]styles/globals.css[.inline-code] into an output file [.inline-code]styles/output.css[.inline-code]. We then import this output file in javascript code.

Starting up the development server again, we see that the Tailwind CSS issue is now solved.

But we ran into another issue:

  
  - Waiting for framework port 3000. This can be configured using the 'targetPort' property in the netlify.toml
  $ concurrently "next dev --turbo" "tailwindcss --input ./styles/globals.css --output ./styles/output.css --watch"
    info  - Loaded env from /var/app/.env
    >>> TURBOPACK (alpha)

    Thank you for trying Next.js v13 with Turbopack! As a reminder,
    Turbopack is currently in alpha and not yet ready for production.
    We appreciate your ongoing support as we work to make it ready
    for everyone.

    Error: You are using configuration and/or tools that are not yet
    supported by Next.js v13 with Turbopack:

    - Unsupported Next.js configuration option(s) (next.config.js)
      The only configurations options supported are:
        - experimental.serverComponentsExternalPackages
        - experimental.transpilePackages
      To use Turbopack, remove other configuration options.
  ....
  
 

For [.inline-code]next.config.js[.inline-code], not all the Webpack supported configurations are currently supported by Turbopack. Here are a few of them:

  1. [.inline-code]env[.inline-code]
    This Next.js feature is using a Webpack plugin called DefinePlugin behind the scenes. More information can be found here:
    next.config.js: Environment Variables | Next.js
    DefinePlugin | webpack
  1. [.inline-code]images -> domains[.inline-code] for [.inline-code]next/image[.inline-code]
    The [.inline-code]domains[.inline-code] is used to specify the allowed hostnames for external images.
  1. Sentry-related [.inline-code]withSentryConfig[.inline-code] and [.inline-code]sentryWebpackPluginOptions[.inline-code]
    Sentry is an error-tracking tool which allows integration with Next.js. But it hasn’t supported building with Turbopack at the moment. More information can be found here:
    Next.js | Sentry Documentation

In conclusion, we were able to migrate to Next.js version 13. But we couldn’t enable Turbopack due to certain features not being supported yet.

Your vision deserves a great dev team.

We're not about tech jargon or over-promising. Instead, we focus on clear communication, transparency in our process, and delivering results that speak for themselves.

Awards won by Hivekind