跳到內容
Next.js 文件架構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 可以作為 Crate 在 Next.js 內部使用,而無需分叉庫或規避設計限制。
  • 效能: 透過切換到 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.com/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 可以自動轉譯和打包本地包(如 Monorepo)或外部依賴項(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 欄位為所有環境(伺服器、邊緣和客戶端)定義變數。或者,使用 compiler.defineServer 僅為伺服器端(伺服器和邊緣)程式碼定義變數

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',
    },
  },
}

構建生命週期鉤子

Next.js 編譯器支援生命週期鉤子,允許你在構建過程中的特定點執行自定義程式碼。目前,支援以下鉤子

runAfterProductionCompile

一個鉤子函式,在生產構建編譯完成後但在執行型別檢查和靜態頁面生成等編譯後任務之前執行。此鉤子提供對專案元資料(包括專案目錄和構建輸出目錄)的訪問,使其適用於第三方工具收集構建輸出(如源對映)。

next.config.js
module.exports = {
  compiler: {
    runAfterProductionCompile: async ({ distDir, projectDir }) => {
      // Your custom code here
    },
  },
}

此鉤子接收一個具有以下屬性的物件

  • distDir:構建輸出目錄(預設為 .next
  • projectDir:專案的根目錄

實驗性功能

SWC 跟蹤分析

你可以將 SWC 的內部轉換跟蹤生成為 Chromium 的 trace 事件格式

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

啟用後,swc 將在 .next/ 下生成名為 swc-trace-profile-${timestamp}.json 的跟蹤檔案。Chromium 的 trace viewer (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.0SWC 壓縮器預設啟用。
v12.3.0SWC 壓縮器 穩定版
v12.2.0添加了 SWC 外掛 實驗性支援。
v12.1.0新增了對 Styled Components、Jest、Relay、移除 React 屬性、傳統裝飾器、移除 Console 和 jsxImportSource 的支援。
v12.0.0Next.js 編譯器 推出