バンドルサイズの「死角」を消す:`sideEffects` フラグによるツリーシェイキングの完全制御
フロントエンド開発において、「なぜ使っていないライブラリのコードがバンドルに含まれているのか?」という問いは、避けては通れない壁です。WebpackやRollupが提供する「ツリーシェイキング(Tree Shaking)」は魔法ではありません。彼らは「このモジュールは副作用がない」と確信できない限り、安全のためにコードを削除しないという極めて保守的な設計思想を持っているからです。
本稿では、`package.json`の `sideEffects` プロパティを極限まで最適化し、ビルドサイズを削ぎ落とすためのアーキテクト視点の戦術を伝授します。
—
1. なぜ `sideEffects` が必要なのか?(理論的背景)
ツリーシェイキングは、ES Modulesの静的構造を利用して「使われていないエクスポート」を除去します。しかし、以下のようなコードが存在する場合、バンドラーは頭を抱えます。
// 例:副作用を持つモジュール
import ‘./global-styles.css’; // グローバルスタイルの注入
console.log(‘初期化を実行’); // プロセスを汚染する副作用
このモジュールをインポートするだけで、DOMの操作やグローバル変数の変更が発生します。バンドラーは「もしこのモジュールを削除したら、アプリの挙動が壊れるのではないか?」と懸念し、たとえその中の関数が一度も使われていなくても、モジュール全体をバンドルに含めてしまいます。
`sideEffects` フラグは、開発者がバンドラーに対して「このモジュール群には副作用がないから、使われていなければ容赦なく消していい」と保証する契約書です。
—
2. `sideEffects` のベストプラクティス構成
プロジェクトの `package.json` に設定すべき、現場で最も堅牢な構成例を示します。
{
“name”: “my-awesome-app”,
“version”: “1.0.0”,
// 1. 基本戦略: プロジェクト全体を「副作用なし」と宣言する
// これにより、バンドラーは未使用モジュールを積極的に削除するようになる
“sideEffects”: false,
// 2. 例外設定: 副作用が必要なファイルだけをホワイトリスト化する
// CSSやSCSSのインポート、polyfillの読み込みなどはここで保護する
“sideEffects”: [
“.css”,
“.scss”,
“src/polyfills.ts”,
“src/global-styles.js”
]
}
なぜこの構成が最強なのか?
- デフォルト `false` の威力: すべてのコンポーネントが単なる関数やコンポーネントであれば、それらは純粋(Pure)であると判断され、未使用なら即座に削除されます。
- ホワイトリストによる安全性: スタイルシートやグローバル初期化処理を明示することで、破壊的な削除を防ぎつつ、それ以外のコードに対して最大の最適化を許可します。
—
3. 実戦:バンドルサイズを「見える化」して追跡する
設定の効果を測れない最適化は、ただの「おまじない」です。以下の神プラグインを導入し、CI環境で自動監視してください。
推奨プラグイン: `webpack-bundle-analyzer`
ビルド生成物を可視化し、何がどの程度の容量を占めているか視覚的に把握します。
開発環境で即座にインストール
npm install –save-dev webpack-bundle-analyzer
webpack.config.js への組み込み例:
const { BundleAnalyzerPlugin } = require(‘webpack-bundle-analyzer’);
module.exports = {
plugins: [
// ビルド時にレポート用HTMLを生成する
new BundleAnalyzerPlugin({
analyzerMode: ‘static’, // サーバーを立ち上げずレポートファイルを出力
openAnalyzer: false,
})
]
};
検証コマンド:
`npm run build` を実行した後、生成された `dist/report.html` を開いてください。`sideEffects: false` を適用する前後で、特定のライブラリ(特にUtility系やアイコンライブラリ)のサイズが劇的に減少しているはずです。
—
4. チーム開発を加速させる「設定共有」の極意
大規模開発では、個々のメンバーが `sideEffects` を意識するのは困難です。以下の運用ルールをCI/CDパイプラインに組み込みましょう。
1. ESLintでの強制: `eslint-plugin-import` を使用し、無駄な副作用のあるインポートを警告するルールを適用します。
2. 型定義ファイルの整備: 自作ライブラリを公開する場合、`package.json` に必ず `sideEffects` を含めてください。これだけで、あなたのライブラリを利用するすべてのチームのアプリが軽量化されます。
3. CIでの回帰テスト: `bundle-size` というライブラリを使い、前回のビルドよりサイズが一定以上増加したらビルドを失敗させるよう設定します。
GitHub Actionsの例
- name: Check bundle size
run: npx bundle-size
# 許容できないサイズ増加を検知し、マージ前にコードレビューを促す
—
最後に:アーキテクトからの助言
`sideEffects` の設定は、単なるビルド設定ではありません。「コードが純粋であること」を重視するアーキテクチャへのコミットメントです。
副作用を最小限に抑え、モジュールを小さく保つことは、テストの容易性、メンテナンス性、そして最終的なパフォーマンスに直結します。ぜひ今日、あなたのプロジェクトの `package.json` を開き、このフラグを適切に設定してみてください。その数行が、ユーザーの体感速度を向上させ、あなたのプロダクトを一段上のステージへと押し上げるはずです。
何か特定のライブラリのツリーシェイキングでお困りですか?その詳細を教えていただければ、さらに踏み込んだチューニングを伝授します。