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として使用でき、ライブラリをフォークしたり設計上の制約を回避する必要がありません。
  • パフォーマンス: SWCに切り替えることで、Next.jsで約3倍高速なFast Refreshと約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のコンパイル用に個々のプロパティを設定できます。

注意: minifytranspileTemplateLiteralspureはまだ実装されていません。進捗はこちらで確認できます。ssrdisplayNameの変換は、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[],
      // デフォルトで有効
      cssProp?: boolean,
      // デフォルトは空
      namespace?: string,
      // まだサポートされていません
      minify?: boolean,
      // まだサポートされていません
      transpileTemplateLiterals?: boolean,
      // まだサポートされていません
      pure?: boolean,
    },
  },
}

Jest

Next.jsコンパイラはテストをトランスパイルし、JestをNext.jsと一緒に設定することを簡素化します:

  • .css.module.css(およびそれらの.scssバリアント)と画像インポートの自動モック
  • SWCを使用してtransformを自動設定
  • .env(およびすべてのバリアント)をprocess.envにロード
  • node_modulesをテスト解決と変換から除外
  • .nextをテスト解決から除外
  • 実験的なSWC変換を有効にするフラグのためにnext.config.jsをロード

まず、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'],
}

// next/jestが非同期のNext.js設定をロードできるように、この方法でcreateJestConfigをエクスポート
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__ディレクトリ内にファイルを生成し、このファイルがルートと見なされて本番ビルドが壊れます。

Reactプロパティの削除

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

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

レガシーデコレータ

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,
      // デフォルトは未定義
      // このオプションにより、コンパイラはどのインポートを調べて何を変換すべきかを判断できます
      // Emotionのエクスポートを再エクスポートする場合でも変換を使用できます
      importMap?: {
        [packageName: string]: {
          [exportName: string]: {
            canonicalImport?: [string, string],
            styledBaseImport?: [string, string],
          }
        }
      },
    },
  },
}

ミニファイ

Next.jsのswcコンパイラは、v13以降デフォルトでミニファイに使用されます。これはTerserよりも7倍高速です。

何らかの理由でTerserが必要な場合は、次のように設定できます。

next.config.js
module.exports = {
  swcMinify: false,
}

モジュールトランスパイル

Next.jsは、ローカルパッケージ(モノレポなど)や外部依存関係(node_modules)からの依存関係を自動的にトランスパイルおよびバンドルできます。これはnext-transpile-modulesパッケージを置き換えます。

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

モジュール化インポート

このオプションはNext.js 13.5でoptimizePackageImportsに置き換えられました。手動でインポートパスを設定する必要がない新しいオプションを使用することをお勧めします。

実験的な機能

SWCトレースプロファイリング

SWCの内部変換トレースをchromiumのトレースイベントフォーマットとして生成できます。

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プラグイン(実験的)

wasmで書かれたSWCの実験的なプラグインサポートを使用して、変換動作をカスタマイズするようにswcの変換を設定できます。

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.0SWCプラグインの実験的サポートが追加。
v12.1.0Styled Components、Jest、Relay、Reactプロパティ削除、レガシーデコレータ、Console削除、jsxImportSourceのサポートが追加。
v12.0.0Next.jsコンパイラが導入