DEV Community

Jen C.
Jen C.

Posted on

Switching Next.js Compiler from Babel to SWC

Resources

Pre-study

Next.js already includes several polyfills by default

As mentioned in the article and the referenced source code, Next.js provides built-in support for many core-js methods by default.

How do I know if I need core-js?

If you're targeting older browsers

How do I know if I need regenerator-runtime?

If there are other packages that depend on it

For example, running the command yarn why regenerator-runtime will produce results like the following, which show that several packages in the project depend on regenerator-runtime. Therefore, it should remain in the dependencies section of the package.json.

Image description

What is next build?

Running next build generates an optimized version of your application for production. HTML, CSS, and JavaScript files are created based on your pages. JavaScript is compiled and browser bundles are minified using the Next.js Compiler to help achieve the best performance and support all modern browsers.

Babel config

Background

  • Our project currently uses Babel as the compiler for Next.js. We're planning to migrate to SWC to simplify the build process and eliminate the need for a custom Babel configuration.
  • The project also includes core-js and regenerator-runtime. We'll need to see whether these dependencies are still required.

Step-by-step guide

Current settings

Babel configuration in the package.json

"babel": {
    "presets": [
      [
        "next/babel",
        {
          "env": {
            "corejs": "3",
            "useBuiltIns": "entry"
          }
        }
      ]
    ],
},
Enter fullscreen mode Exit fullscreen mode

polyfills.js in the project

import 'core-js/stable';
import 'regenerator-runtime/runtime';
Enter fullscreen mode Exit fullscreen mode

Packages core-js and regenerator-runtime in the package.json

"dependencies": {

    ...

    "core-js": "^3.16.0",
    ...

    "regenerator-runtime": "^0.13.9",
Enter fullscreen mode Exit fullscreen mode

Babel related packages in the package.json

 "devDependencies": {
    "@babel/core": "^7.26.10",

    ...

    "babel-jest": "^27.0.6",

    ...
}
Enter fullscreen mode Exit fullscreen mode

Polyfill-related configuration in the Next.js configuration file, next.config.js

...

 webpack(config, { dev }) {
    const { plugins, entry: originalEntry } = config;

    if (dev) {
      // Change it for VSCode debug
      config.devtool = 'cheap-module-eval-source-map';
    } else {
      config.entry = async () => {
        const entries = await originalEntry();

        if (
          entries['main.js'] &&
          !entries['main.js'].includes('./polyfills.js')
        ) {
          entries['main.js'].unshift('./polyfills.js');
        }

        return entries;
      };

      ...
Enter fullscreen mode Exit fullscreen mode

Solution 1: Remove the Babel configuration from package.json (Doesn't work since the project uses Enzyme for testing React)

Get this error when running unit tests

Image description

 Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.
Enter fullscreen mode Exit fullscreen mode

Solution

Setup and config @swc/jest

Setup Jest config and SWC config

Get another error

Image description

Caused by:
        Syntax Error

      at Compiler.transformSync (node_modules/@swc/core/index.js:249:29)
      at transformSync (node_modules/@swc/core/index.js:359:21)
      at Object.process (node_modules/@swc/jest/index.js:73:45)
      at ScriptTransformer.transformSource (node_modules/@jest/transform/build/ScriptTransformer.js:612:31)
      at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:758:40)
      at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:815:19)
Enter fullscreen mode Exit fullscreen mode

Root cause

Because the project uses Enzyme to test React components, the error occurred after switching the transpiler from Babel to SWC.

Solution 2: Use SWC for production and development, and Babel only during testing

Remove the Babel configuration in the package.json file

Create a Babel configuration file, babel.config.dev.js, for testing use

module.exports = function (api) {
  api.cache(true);

  return {
    presets: ['next/babel'],
  };
};
Enter fullscreen mode Exit fullscreen mode

Update scripts in package.json

In development and production, delete babel.config.js to allow Next.js to use SWC as the default compiler.

In test environments, copy babel.config.dev.js to babel.config.js.

"scripts": {

    ... 

    "dev": "rm -f babel.config.js && next dev",
    "build": "rm -f babel.config.js && next build",
    "test": "cp babel.config.dev.js babel.config.js && jest",

    ...

}
Enter fullscreen mode Exit fullscreen mode

Results

Bundle size (Gzipped size): Babel vs Built-in SWC

Using Next.js’s built-in SWC compiler results in a slightly smaller bundle size compared to using Babel.

Babel: 869.86 KB

Image description

SWC: 826.33 KB

Image description

First Load JS Shared by All: Babel vs Built-in SWC

The First Load JavaScript shared by all pages is smaller when using Next.js’s built-in SWC compared to Babel.

Babel: 324 kB

Image description

SWC: 318 kB

Image description

Build time

To compare the build time difference between the two compilers, delete the .next folder in the project and run the build command.

The results show that using SWC is approximately 10 seconds faster than using Babel.

Babel: 34.10s

Image description

SWC: 22.67s

Image description

Other Notes

How to check which complier is used now?

Add a console.log statement in the Babel configuration file so that when the project uses Babel, the message is printed in the output.

For example,

console.log("💡 Babel is running!");

module.exports = function (api) {
  api.cache(true);

  return {
    presets: ['next/babel'],
  };
};
Enter fullscreen mode Exit fullscreen mode

Or when you see the message SWC disabled in the command line output during the build phase.

How to prevent fallback to use Babel?

Ensure there is no Babel configuration file (e.g., .babelrc, babel.config.js) in the production environment to allow Next.js to use its built-in SWC compiler.

Top comments (0)