跳到内容
介绍架构Next.js 编译器

Next.js 编译器

Next.js 编译器使用 SWC 以 Rust 编写,允许 Next.js 转换和压缩你的 JavaScript 代码以用于生产环境。它取代了 Babel 用于单个文件,以及 Terser 用于压缩输出包。

使用 Next.js 编译器进行编译比 Babel 快 17 倍,并且自 Next.js 版本 12 起默认启用。如果你有现有的 Babel 配置或正在使用不支持的功能,你的应用程序将选择退出 Next.js 编译器并继续使用 Babel。

为什么选择 SWC?

SWC 是一个可扩展的、基于 Rust 的平台,用于下一代快速开发者工具。

SWC 可以用于编译、压缩、捆绑等,并且被设计为可扩展的。你可以调用它来执行代码转换(内置或自定义)。这些转换通过更高级别的工具(如 Next.js)进行。

我们选择基于 SWC 构建有以下几个原因:

  • 可扩展性: SWC 可以作为 Next.js 内部的 Crate 使用,而无需 fork 库或绕过设计约束。
  • 性能: 通过切换到 SWC,我们在 Next.js 中实现了快约 3 倍的快速刷新和快约 5 倍的构建速度,并且仍有更多的优化空间正在进行中。
  • WebAssembly: Rust 对 WASM 的支持对于支持所有可能的平台并将 Next.js 开发带到任何地方至关重要。
  • 社区: Rust 社区和生态系统非常棒并且仍在不断发展。

支持的功能

Styled Components

我们正在努力将 babel-plugin-styled-components 移植到 Next.js 编译器。

首先,更新到最新版本的 Next.js:npm install next@latest。然后,更新你的 next.config.js 文件

next.config.js
module.exports = {
  compiler: {
    styledComponents: true,
  },
}

对于高级用例,你可以为 styled-components 编译配置各个属性。

注意:ssrdisplayName 转换是在 Next.js 中使用 styled-components 的主要要求。

next.config.js
module.exports = {
  compiler: {
    // see https://styled-components.npmjs.net.cn/docs/tooling#babel-plugin for more info on the options.
    styledComponents: {
      // Enabled by default in development, disabled in production to reduce file size,
      // setting this will override the default for all environments.
      displayName?: boolean,
      // Enabled by default.
      ssr?: boolean,
      // Enabled by default.
      fileName?: boolean,
      // Empty by default.
      topLevelImportPaths?: string[],
      // Defaults to ["index"].
      meaninglessFileNames?: string[],
      // Enabled by default.
      minify?: boolean,
      // Enabled by default.
      transpileTemplateLiterals?: boolean,
      // Empty by default.
      namespace?: string,
      // Disabled by default.
      pure?: boolean,
      // Enabled by default.
      cssProp?: boolean,
    },
  },
}

Jest

Next.js 编译器转换你的测试,并简化了将 Jest 与 Next.js 一起配置的过程,包括:

  • 自动模拟 .css.module.css(及其 .scss 变体)和图像导入
  • 使用 SWC 自动设置 transform
  • .env(和所有变体)加载到 process.env
  • 忽略来自测试解析和转换的 node_modules
  • 忽略来自测试解析的 .next
  • 加载 next.config.js 以启用实验性 SWC 转换的标志

首先,更新到最新版本的 Next.js:npm install next@latest。然后,更新你的 jest.config.js 文件

jest.config.js
const nextJest = require('next/jest')
 
// Providing the path to your Next.js app which will enable loading next.config.js and .env files
const createJestConfig = nextJest({ dir: './' })
 
// Any custom config you want to pass to Jest
const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
}
 
// createJestConfig is exported in this way to ensure that next/jest can load the Next.js configuration, which is async
module.exports = createJestConfig(customJestConfig)

Relay

要启用 Relay 支持

next.config.js
module.exports = {
  compiler: {
    relay: {
      // This should match relay.config.js
      src: './',
      artifactDirectory: './__generated__',
      language: 'typescript',
      eagerEsModules: false,
    },
  },
}

须知:在 Next.js 中,pages 目录中的所有 JavaScript 文件都被视为路由。因此,对于 relay-compiler,你需要指定 artifactDirectory 配置设置在 pages 之外,否则 relay-compiler 将在 __generated__ 目录中源文件旁边生成文件,并且此文件将被视为路由,这将破坏生产环境构建。

移除 React 属性

允许移除 JSX 属性。这通常用于测试。类似于 babel-plugin-react-remove-properties

要移除匹配默认正则表达式 ^data-test 的属性

next.config.js
module.exports = {
  compiler: {
    reactRemoveProperties: true,
  },
}

要移除自定义属性

next.config.js
module.exports = {
  compiler: {
    // The regexes defined here are processed in Rust so the syntax is different from
    // JavaScript `RegExp`s. See https://docs.rs/regex.
    reactRemoveProperties: { properties: ['^data-custom$'] },
  },
}

移除 Console

此转换允许移除应用程序代码(非 node_modules)中的所有 console.* 调用。类似于 babel-plugin-transform-remove-console

移除所有 console.* 调用

next.config.js
module.exports = {
  compiler: {
    removeConsole: true,
  },
}

移除 console.* 输出,但 console.error 除外

next.config.js
module.exports = {
  compiler: {
    removeConsole: {
      exclude: ['error'],
    },
  },
}

旧式装饰器

Next.js 将自动检测 jsconfig.jsontsconfig.json 中的 experimentalDecorators。旧式装饰器通常与旧版本的库(如 mobx)一起使用。

此标志仅为兼容现有应用程序而支持。我们不建议在新应用程序中使用旧式装饰器。

首先,更新到最新版本的 Next.js:npm install next@latest。然后,更新你的 jsconfig.jsontsconfig.json 文件

{
  "compilerOptions": {
    "experimentalDecorators": true
  }
}

importSource

Next.js 将自动检测 jsconfig.jsontsconfig.json 中的 jsxImportSource 并应用它。这通常与诸如 Theme UI 之类的库一起使用。

首先,更新到最新版本的 Next.js:npm install next@latest。然后,更新你的 jsconfig.jsontsconfig.json 文件

{
  "compilerOptions": {
    "jsxImportSource": "theme-ui"
  }
}

Emotion

我们正在努力将 @emotion/babel-plugin 移植到 Next.js 编译器。

首先,更新到最新版本的 Next.js:npm install next@latest。然后,更新你的 next.config.js 文件

next.config.js
 
module.exports = {
  compiler: {
    emotion: boolean | {
      // default is true. It will be disabled when build type is production.
      sourceMap?: boolean,
      // default is 'dev-only'.
      autoLabel?: 'never' | 'dev-only' | 'always',
      // default is '[local]'.
      // Allowed values: `[local]` `[filename]` and `[dirname]`
      // This option only works when autoLabel is set to 'dev-only' or 'always'.
      // It allows you to define the format of the resulting label.
      // The format is defined via string where variable parts are enclosed in square brackets [].
      // For example labelFormat: "my-classname--[local]", where [local] will be replaced with the name of the variable the result is assigned to.
      labelFormat?: string,
      // default is undefined.
      // This option allows you to tell the compiler what imports it should
      // look at to determine what it should transform so if you re-export
      // Emotion's exports, you can still use transforms.
      importMap?: {
        [packageName: string]: {
          [exportName: string]: {
            canonicalImport?: [string, string],
            styledBaseImport?: [string, string],
          }
        }
      },
    },
  },
}

压缩

自 v13 起,Next.js 的 swc 编译器默认用于压缩。这比 Terser 快 7 倍。

须知: 从 v15 开始,无法使用 next.config.js 自定义压缩。已删除对 swcMinify 标志的支持。

模块转译

Next.js 可以自动转译和捆绑来自本地包(如 monorepos)或来自外部依赖项(node_modules)的依赖项。这取代了 next-transpile-modules 包。

next.config.js
module.exports = {
  transpilePackages: ['@acme/ui', 'lodash-es'],
}

模块化导入

此选项已被 Next.js 13.5 中的 optimizePackageImports 取代。我们建议升级以使用新的选项,该选项不需要手动配置导入路径。

Define(构建期间替换变量)

define 选项允许你在构建时静态地替换代码中的变量。该选项接受一个对象作为键值对,其中键是将要替换的变量,值是相应的替换值。

next.config.js 中使用 compiler.define 字段

next.config.js
module.exports = {
  compiler: {
    define: {
      MY_STRING_VARIABLE: JSON.stringify('my-string'),
      MY_NUMBER_VARIABLE: '42',
    },
  },
}

实验性功能

SWC 跟踪分析

你可以生成 SWC 的内部转换跟踪,格式为 chromium 的 trace event format

next.config.js
module.exports = {
  experimental: {
    swcTraceProfiling: true,
  },
}

启用后,swc 将在 .next/ 下生成名为 swc-trace-profile-${timestamp}.json 的跟踪文件。Chromium 的跟踪查看器 (chrome://tracing/,https://ui.perfetto.dev/) 或兼容的火焰图查看器 (https://www.speedscope.app/) 可以加载和可视化生成的跟踪。

SWC 插件(实验性)

你可以配置 swc 的转换以使用 SWC 的实验性插件支持(用 wasm 编写)来自定义转换行为。

next.config.js
module.exports = {
  experimental: {
    swcPlugins: [
      [
        'plugin',
        {
          ...pluginOptions,
        },
      ],
    ],
  },
}

swcPlugins 接受元组数组以配置插件。插件的元组包含插件的路径和一个用于插件配置的对象。插件的路径可以是 npm 模块包名称,也可以是 .wasm 二进制文件本身的绝对路径。

不支持的功能

当你的应用程序具有 .babelrc 文件时,Next.js 将自动回退到使用 Babel 来转换单个文件。这确保了与利用自定义 Babel 插件的现有应用程序的向后兼容性。

如果你正在使用自定义 Babel 设置,请分享你的配置。我们正在努力移植尽可能多的常用 Babel 转换,并在未来支持插件。

版本历史

版本变更
v13.1.0模块转译模块化导入 稳定版。
v13.0.0默认启用 SWC 压缩器。
v12.3.0SWC 压缩器 稳定版
v12.2.0添加了 SWC 插件 实验性支持。
v12.1.0添加了对 Styled Components、Jest、Relay、移除 React 属性、旧式装饰器、移除 Console 和 jsxImportSource 的支持。
v12.0.0Next.js 编译器 引入