mcpField
S
swc-plugin-compatibility

swc-plugin-compatibility

github.com/lingui開発10280 回インストール1 週間前に更新
リポジトリ

swc-plugin-compatibility について

`@lingui/swc-plugin` と SWC ホストの互換性エラーを調査するスキルです。ホストのバージョン確認、互換プラグインの選定と固定、Next.js・Vite・Rspack でのマクロ変換検証を支援します。

主な機能

  1. 01解決済み SWC ホストの特定
  2. 02互換プラグインバージョンの選定
  3. 03`@lingui/core` の peer 要件確認
  4. 04プラグインの厳密なバージョン固定
  5. 05Babel フォールバック案内

活用シーン

  1. 01SWC Wasm プラグインのビルド失敗を調査
  2. 02ホスト更新後のプラグイン選定
  3. 03ビルドで Lingui マクロの出力を確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/lingui/skills --skill swc-plugin-compatibility

インストール後、Claude Code で/swc-plugin-compatibilityを入力して読み込まれたか確認します。

詳細

SWC プラグインの互換性

ビルド中に次のようなエラーが表示された場合:

failed to invoke plugin on 'Some("/app/src/file.ts")'
failed to run Wasm plugin transform. Please ensure the version of `swc_core` used by the plugin is compatible with the host runtime.
    swc_plugin_runner: <n>
: Failed to deserialize program received from host
Failed to execute SWC plugin                      (Next.js / Turbopack wording of the same failure)
RuntimeError: out of bounds memory access         (older hosts)
LayoutError called Result::unwrap()               (older hosts)

これは、コードや Lingui のバグではありません。 インストールされている @lingui/swc-plugin は、SWC ホストが実行できないバージョンの swc_core に対してビルドされています。

この問題が発生する理由

@lingui/swc-plugin の各リリースは、固定された 1 つの swc_core バージョンに対してコンパイルされています。プラグインの互換性表に、対応するバージョンが記載されています。ホスト(Next.js にバンドルされた SWC、または @vitejs/plugin-react-swc/Rspack が解決する @swc/core)は、ある範囲の swc_core バージョンのプラグインを受け入れます。その範囲外では、Wasm プラグインは渡された AST をデシリアライズできず、マクロを使うすべてのファイルでビルドが失敗します。

SWC では時間をかけてプラグイン ABI が安定化しているため、バージョンの不一致は以前より減っていますが、それでもホストがプラグインより先行したり、プラグインがホストより先行したりすることがあります(それぞれの例については、lingui/swc-plugin の #250 と #253 を参照してください)。対応関係は必ず確認し、思い込みで判断しないでください。

修正方法

ステップ 1:ホストと解決済みバージョンを特定する
プロジェクト内の手がかりホストバージョンの確認先
依存関係に next があり、.babelrc がないNext.js にバンドルされた SWCnpm ls next
@vitejs/plugin-react-swc@swc/corenpm ls @swc/core — プラグインが宣言するキャレット範囲ではなく、ロックファイルで解決されたバージョン
Rspack/@swc/core を直接使用@swc/corenpm ls @swc/core

Next.js は SWC を内包しており、package.json にある @swc/core は無視します。swc_core を決めるのは Next.js のバージョンだけです。Vite では、package.json が同一の 2 つのプロジェクトでも、異なるバージョンの @swc/core に解決される場合があります。信頼できる情報源はロックファイルです。

ステップ 2:プラグインのバージョンを選ぶ
  1. ホストが受け入れる swc_core の範囲を確認します。エラーメッセージには通常、https://plugins.swc.rs/versions/from-plugin-runner/<n> の URL が表示されます。ブラウザーで開いてください。Next.js の場合は、https://plugins.swc.rs でランタイムに next を選択し、解決済みバージョンを指定します。このサイトはクライアント側でレンダリングされるため、通常の fetch では空のページが返されます。代わりに、ホスト自体が指定しているバージョンを確認します。Next.js の場合は vercel/next.js のタグ(v<version>)にあるルートの Cargo.toml の swc_core、@swc/core の場合は GitHub のリリースノートを確認してください。
  2. プラグインの互換性表から、その範囲内の swc_core を使う 最新の @lingui/swc-plugin を選びます。
  3. ピア依存関係を確認します:npm view @lingui/swc-plugin@<version> peerDependencies。各プラグインのメジャーバージョンは、対応する @lingui/core のメジャーバージョンを必須のピア依存関係として要求します(新しいプラグインのメジャーバージョンが、前の core メジャーバージョンにも対応している場合もあります)。インストール済みの @lingui/core がピア依存関係の対象外となる候補は使えません。その場合、ビルドが失敗するのではなく、インストールが ERESOLVE で失敗します。条件を満たす次に新しいバージョンを選ぶか、「互換性のあるバージョンが存在しない場合」を参照してください。

互換性サイトの情報が、以前リリースより遅れていたことがあります。表とサイトの内容が一致しない場合、またはホストのバージョンがどちらにも記載されていない場合は、ビルドで判断してください。最新のプラグインから試し、マクロを使用するファイルがコンパイルできるまで、swc_core の表を 1 行ずつさかのぼります。

ホストごとに独立してバージョンが変わるため、1 つのリポジトリ内にある 2 つのホスト(Next.js アプリと Vite アプリなど)で、異なるプラグインバージョンが必要になるのは自然なことです。

ステップ 3:バージョンを厳密に固定して確認する
{
  "devDependencies": {
    "@lingui/swc-plugin": "<exact version>"
  }
}

バージョンは厳密に指定し(^ や ~ は付けません)、通常の依存関係の更新でバージョンが変わらないようにします。マクロを使うファイルのビルドが成功し、レンダリング結果にマクロのソースではなく翻訳済みのテキストが表示されれば完了です。

動作を維持する

  1. プラグインのバージョンを正確に固定し、Renovate/Dependabot の自動マージ対象から除外してください。互換性表を確認してから、意図的にバージョンを上げてください。
  2. ホストのアップグレードもプラグインのアップグレードとして扱ってください。 ホストはマイナーリリースやパッチリリースで swc_core を変更するため、Next.js または @vitejs/plugin-react-swc のバージョンを上げる際も、同じ確認が必要です。両方のパッケージを同じ更新グループにまとめてください。
  3. SWC またはプラグインに影響するアップグレードの後は、必ずビルドしてください。 確認になるのは変更履歴ではなく、ビルドです。

@lingui/swc-plugin のバージョンは、他の @lingui/* のバージョンには連動しません。独自のリリースサイクルでリリースされるため、バージョン番号からは、peer フィールド以外に、どの @lingui/core と組み合わせられるかは分かりません。

例:Next.js の設定

// next.config.mjs
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    swcPlugins: [
      ['@lingui/swc-plugin', {
        // Plugin options
      }],
    ],
  },
};

export default nextConfig;

例:.swcrc の設定

{
  "$schema": "https://json.schemastore.org/swcrc",
  "jsc": {
    "experimental": {
      "plugins": [
        ["@lingui/swc-plugin", {}]
      ]
    }
  }
}

例:Vite の設定

// vite.config.ts
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import { lingui } from "@lingui/vite-plugin";

export default defineConfig({
  plugins: [
    react({ plugins: [["@lingui/swc-plugin", {}]] }),
    lingui(),
  ],
});

サイレントな失敗:プラグインエントリーの形式が誤っている

すべての SWC プラグインエントリーは、オプションが空でも [name, options] のタプルである必要があります。プラグイン名を文字列だけで渡すと、マクロ変換はサイレントに無効になります。ビルドは成功しますが、<Trans> は解決されず、メッセージはマクロの出力そのままで表示されます。

// ❌ Silently does nothing
react({ plugins: ["@lingui/swc-plugin"] })

// ✅ Tuple with options object
react({ plugins: [["@lingui/swc-plugin", {}]] })

Next.js の swcPlugins と .swcrc の plugins 配列にも同じことが当てはまります。

互換性のあるバージョンがない場合は?

プロジェクトの @lingui/core と一緒にインストールできるプラグインのバージョンがホストに適合しない場合は、推測せず、明確な選択をしてください。

  1. ホストを、swc_core の範囲に一致するプラグインがあるバージョンに変更する(通常は新しいホストの方が、新しいプラグインに対応しています)
  2. Babel 変換に切り替える(@lingui/babel-plugin-lingui-macro)— 以下の注意事項を参照してください
  3. https://github.com/lingui/swc-plugin で issue または PR を作成する

--legacy-peer-deps でインストールを強行したり、古いプラグインの peer を満たすために @lingui/core をダウングレードしたりするのは、選択肢に含まれません。前者はビルドまで不一致を見えなくし、後者はビルドツールに合わせるためにランタイムを後退させます。

Next.js での Babel フォールバック
npm install -D @lingui/babel-plugin-lingui-macro babel-plugin-macros @babel/types
// .babelrc
{ "presets": ["next/babel"], "plugins": ["macros"] }

experimental.swcPlugins エントリーを削除してください。Babel を使う場合に必要となる、SWC プラグインでは不要だったものが3つあります。

  1. @babel/types を明示的にインストールすること。 Next は独自の Babel をバンドルしており、プラグインからは利用できません。これをインストールしないと、ビルドは Cannot find package '@babel/types' で失敗します。
  2. lingui.config.ts(または .js/.mjs)。 Babel マクロはコンパイル時にこのファイルを読み込みます。SWC プラグインは読み込まなかったため、これなしで動作していたプロジェクトはここで失敗します。
  3. .babelrc を使うと、プロジェクト全体で Next の SWC コンパイラーが無効になることを受け入れること。 Next は Disabled SWC as replacement for Babel because of custom Babel configuration と出力し、それ以降 next.config の compiler オプションは無視されます。ビルドは遅くなるため、可能であればホストの変更を優先してください。
Babel フォールバックの注意点:@vitejs/plugin-react 6

@vitejs/plugin-react@6 では内蔵 Babel が削除され、babel オプションも完全に削除されました。v6 以降では、次の従来の形式は:

react({ babel: { plugins: ["@lingui/babel-plugin-lingui-macro"] } })

動作しません。TypeScript の設定では TS2353(「babel does not exist in type...」)で失敗し、通常の JS 設定ではサイレントに無視されるため、マクロは変換されません。

Vite での選択肢:

  • SWC を使い続ける:上記の手順で選んだ、バージョンを正確に固定した @lingui/swc-plugin と @vitejs/plugin-react-swc を使う(推奨)
  • マクロを独立した Babel パスとして実行する(Vite 8 では @rolldown/plugin-babel、Vite ≤ 7 では vite-plugin-babel)。設定方法については lingui-framework-setup スキルを参照してください
  • babel オプションを引き続きサポートする @vitejs/plugin-react@^5 にバージョンを固定する

コメント