WebpackからViteへの移行:「CommonJSの亡霊」を鎮め、ビルド速度を極限まで引き上げるアーキテクチャ設計術
Webpackの柔軟な「何でもあり」なエコシステムからViteのネイティブESM環境へ移行する際、多くのエンジニアが直面する壁。それは、コードの書き換えではなく、「CommonJS(CJS)という過去の遺産」がViteの最適化エンジンと衝突する現象です。
これは単なるエラーの解決ではなく、モジュール解決の深淵を理解しているかどうかの試金石です。今日は、レガシーライブラリの泥沼を抜け出し、開発体験を異次元へ引き上げるための「Viteアーキテクチャの真髄」を伝授します。
—
1. なぜViteで「ESM非対応ライブラリ」がエラーを吐くのか
Webpackは、内部的に`enhanced-resolve`を用い、CJSとESMの境界を「何とかして」強引に解決していました。一方、ViteはブラウザのネイティブESMを前提としており、依存関係の事前バンドル(`esbuild`による`optimizeDeps`)を行います。
問題の本質: レガシーライブラリが`require`で動的にモジュールをロードしたり、`module.exports`を複雑に書き換えたりしている場合、Viteの静的解析が追いつかず、ランタイムで「`exports is not defined`」といった例外が発生します。
解決策:`optimizeDeps`による「強制的事前コンパイル」
Viteに「このライブラリは怪しいから、事前にESMへ変換してキャッシュしておけ」と指示を出すのが、最もクリーンな解決策です。
// vite.config.ts
export default defineConfig({
optimizeDeps: {
// インポート解決が不安定なライブラリをここに列挙
include: [‘legacy-library-a’, ‘another-broken-pkg > child-dependency’],
// 逆に、ビルド時に問題を起こす特定のモジュールを最適化対象から外す
exclude: [‘@monorepo/shared-module’]
}
});
なぜこれが必要か: `include`に指定することで、Viteは初回起動時に`node_modules/.vite`配下に最適化済みファイルを生成します。これにより、ブラウザへのリクエスト時に発生する「大量のモジュールリクエスト(ウォーターフォール)」が解消され、開発サーバーの爆速化が実現します。
—
2. 最終手段:`vite-plugin-commonjs` の正しい使い所
それでも解決しない場合、ライブラリの構造がCJSの変態的な挙動に依存しています。この場合、`vite-plugin-commonjs` を導入しますが、「全ライブラリに適用するのはアンチパターン」です。
import { viteCommonjs } from ‘@originjs/vite-plugin-commonjs’;
export default defineConfig({
plugins: [
viteCommonjs({
// 必要な箇所のみに限定適用する設計思想
filter: (id) => id.includes(‘legacy-module-name’)
})
]
});
※注意:このプラグインはビルド後のバンドルサイズを増大させるリスクがあります。あくまで「一時的な回避策」として、該当ライブラリのIssueを追う姿勢を忘れないでください。
—
3. 生産性を極限まで高める「テックリードの隠し味」
ビルド設定を整えるだけでは、チームの生産性は上がりません。以下のツールと習慣を導入してください。
① 神プラグイン:`vite-plugin-checker`
Viteは爆速ですが、`tsc`(型チェック)を別プロセスで走らせないと、型エラーに気づかず開発を進めてしまうリスクがあります。
npm install -D vite-plugin-checker
これをプラグインに追加するだけで、開発サーバーを立ち上げた瞬間に型エラーがコンソールに通知されます。「ビルドして初めて型エラーを知る」という無駄な時間をゼロにできます。
② チーム共有の環境設定:`vite.config.ts`の分離
大規模プロジェクトでは、設定ファイルが肥大化します。以下のようにディレクトリ分けし、`defineConfig`をモジュール化して管理するのが「プロの流儀」です。
/config
├─ vite.base.ts # 共通設定(エイリアスなど)
├─ vite.proxy.ts # ローカル開発用プロキシ設定
└─ vite.plugins.ts # プラグインの動的生成
—
4. チーム開発における絶対ルール
ビルドツールを移行する際は、以下のルールを`README.md`ではなく、`package.json`の`scripts`に込めてください。
- `”dev”: “vite –force”` は厳禁:
キャッシュを毎回捨てるのはViteの恩恵を自ら捨てている行為です。「なぜ遅いのか」を調査せず、力技で解決しようとする文化をチームから排除してください。
- `optimizeDeps`の変更はPRで明示:
依存関係の最適化設定を変えた際は、必ず`package-lock.json`の変更とともに、`node_modules/.vite`の生成過程に影響が出ることを考慮し、CI上のキャッシュ設定を見直すこと。
—
まとめ:アーキテクトからのメッセージ
WebpackからViteへの移行は、単なるツールの乗り換えではありません。それは「ブラウザのネイティブ能力を最大限に活かすアーキテクチャへの転換」です。
レガシーライブラリのトラブルに遭遇したとき、まずは「なぜこのツールは今、CJSの海で溺れているのか」という原因を突き止めてください。`optimizeDeps`を使いこなし、Viteのキャッシュ機構を理解すれば、あなたのプロジェクトはWebpack時代とは比べ物にならないほど、軽量で俊敏なフロントエンド基盤へと進化するはずです。
さあ、設定ファイルを書き換え、ビルド時間を「待ち時間」ではなく「思考の時間」へと変えましょう。