Resources
- Next.js Compiler
- SWC disabled
- Why you should use SWC (and not Babel)
- Why You Should Replace Babel with SWC in Next.js
- What is Speedy Web Compiler? SWC Explained With Examples
- core-js
- regenerator-runtime
- Enzyme
- How to analyze your Next.js app bundles
Pre-study
Next.js already includes several polyfills by default
- https://nextjs.org/docs/architecture/supported-browsers#polyfills
- https://github.com/vercel/next.js/blob/canary/packages/next-polyfill-nomodule/src/index.js
- https://www.npmjs.com/package/next?activeTab=dependencies
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.
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
andregenerator-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"
}
}
]
],
},
polyfills.js in the project
import 'core-js/stable';
import 'regenerator-runtime/runtime';
Packages core-js
and regenerator-runtime
in the package.json
"dependencies": {
...
"core-js": "^3.16.0",
...
"regenerator-runtime": "^0.13.9",
Babel related packages in the package.json
"devDependencies": {
"@babel/core": "^7.26.10",
...
"babel-jest": "^27.0.6",
...
}
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;
};
...
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
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.
Solution
Setup and config @swc/jest
Setup Jest config and SWC config
Get another error
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)
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'],
};
};
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",
...
}
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
SWC: 826.33 KB
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
SWC: 318 kB
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
SWC: 22.67s
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'],
};
};
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)