Menu

Next.js 编译器

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

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

为什么选择 SWC?

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

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

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

  • 可扩展性: SWC 可以作为 Crate 在 Next.js 内部使用,无需 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 编译配置单个属性。

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

next.config.js
module.exports = {
  compiler: {
    // 有关选项的更多信息,请参见 https://styled-components.com/docs/tooling#babel-plugin
    styledComponents: {
      // 在开发环境中默认启用,在生产环境中禁用以减小文件大小,
      // 设置此项将覆盖所有环境的默认值。
      displayName?: boolean,
      // 默认启用。
      ssr?: boolean,
      // 默认启用。
      fileName?: boolean,
      // 默认为空。
      topLevelImportPaths?: string[],
      // 默认为 ["index"]。
      meaninglessFileNames?: string[],
      // 默认启用。
      minify?: boolean,
      // 默认启用。
      transpileTemplateLiterals?: boolean,
      // 默认为空。
      namespace?: string,
      // 默认禁用。
      pure?: boolean,
      // 默认启用。
      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')
 
// 提供 Next.js 应用的路径,这将启用加载 next.config.js 和 .env 文件
const createJestConfig = nextJest({ dir: './' })
 
// 你想传递给 Jest 的任何自定义配置
const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
}
 
// createJestConfig 以这种方式导出,以确保 next/jest 可以加载异步的 Next.js 配置
module.exports = createJestConfig(customJestConfig)

Relay

要启用 Relay 支持:

next.config.js
module.exports = {
  compiler: {
    relay: {
      // 这应该与 relay.config.js 匹配
      src: './',
      artifactDirectory: './__generated__',
      language: 'typescript',
      eagerEsModules: false,
    },
  },
}

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

Remove React Properties

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

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

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

要删除自定义属性:

next.config.js
module.exports = {
  compiler: {
    // 这里定义的正则表达式在 Rust 中处理,因此语法与
    // JavaScript `RegExp` 不同。请参见 https://docs.rs/regex。
    reactRemoveProperties: { properties: ['^data-custom$'] },
  },
}

Remove Console

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

删除所有 console.* 调用:

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

删除除 console.error 之外的 console.* 输出:

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

Legacy Decorators

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

此标志仅支持与现有应用程序的兼容性。我们不建议在新应用程序中使用传统装饰器。

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

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

importSource

Next.js 将自动检测 jsconfig.json 或 tsconfig.json 中的 jsxImportSource 并应用它。这通常与 Theme UI 等库一起使用。

首先,更新到最新版本的 Next.js:npm install next@latest。然后,更新你的 jsconfig.json 或 tsconfig.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 | {
      // 默认为 true。当构建类型为 production 时将被禁用。
      sourceMap?: boolean,
      // 默认为 'dev-only'。
      autoLabel?: 'never' | 'dev-only' | 'always',
      // 默认为 '[local]'。
      // 允许的值:`[local]` `[filename]` 和 `[dirname]`
      // 此选项仅在 autoLabel 设置为 'dev-only' 或 'always' 时有效。
      // 它允许你定义生成标签的格式。
      // 格式通过字符串定义,其中可变部分用方括号 [] 括起来。
      // 例如 labelFormat: "my-classname--[local]",其中 [local] 将被替换为结果分配给的变量名称。
      labelFormat?: string,
      // 默认为 undefined。
      // 此选项允许你告诉编译器应该
      // 查看哪些导入以确定应该转换什么,因此如果你重新导出
      // Emotion 的导出,你仍然可以使用转换。
      importMap?: {
        [packageName: string]: {
          [exportName: string]: {
            canonicalImport?: [string, string],
            styledBaseImport?: [string, string],
          }
        }
      },
    },
  },
}

Minification

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

值得注意的是:从 v15 开始,无法使用 next.config.js 自定义压缩。对 swcMinify 标志的支持已被移除。

Module Transpilation

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

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

Modularize Imports

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

Define(在构建期间替换变量)

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

使用 next.config.js 中的 compiler.define 字段为所有环境(server、edge 和 client)定义变量。或者,使用 compiler.defineServer 仅为服务器端(server 和 edge)代码定义变量:

next.config.js
module.exports = {
  compiler: {
    define: {
      MY_VARIABLE: 'my-string',
      'process.env.MY_ENV_VAR': 'my-env-var',
    },
    defineServer: {
      MY_SERVER_VARIABLE: 'my-server-var',
    },
  },
}

Build Lifecycle Hooks

Next.js 编译器支持生命周期钩子,允许你在构建过程中的特定点运行自定义代码。目前支持以下钩子:

runAfterProductionCompile

一个钩子函数,在生产构建编译完成后但在运行编译后任务(如类型检查和静态页面生成)之前执行。此钩子提供对项目元数据的访问,包括项目目录和构建输出目录,使其对第三方工具收集构建输出(如 sourcemaps)非常有用。

next.config.js
module.exports = {
  compiler: {
    runAfterProductionCompile: async ({ distDir, projectDir }) => {
      // 你的自定义代码在这里
    },
  },
}

该钩子接收一个具有以下属性的对象:

  • distDir:构建输出目录(默认为 .next)
  • projectDir:项目的根目录

实验性功能

SWC Trace profiling

你可以将 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 Plugins(实验性)

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

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

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

不支持的功能

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

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

版本历史

VersionChanges
v13.1.0Module Transpilation 和 Modularize Imports 稳定版。
v13.0.0SWC Minifier 默认启用。
v12.3.0SWC Minifier 稳定版。
v12.2.0添加 SWC Plugins 实验性支持。
v12.1.0添加对 Styled Components、Jest、Relay、Remove React Properties、Legacy Decorators、Remove Console 和 jsxImportSource 的支持。
v12.0.0Next.js 编译器引入。