「tree shaking」という言葉は Rollup から来ており、使われていないコードを木の葉のように「振り落とす」という意味です。Webpack 2 からサポートされていますが、正しく設定しないと機能しません。
基本原理
Tree shaking は ES モジュールの静的な構造(import/export はコンパイル時に決定され、動的に変更できない)に依存します:
javascript
// ES モジュール:静的 — コンパイル時に解析可能
import { add } from "./math"; // add のみを使用
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
} // インポートされていない — 削除可能
// CommonJS:動的 — 解析不可
const math = require("./math"); // オブジェクト全体がインポートされる。どの部分が使われるか不明
const method = "add";
math[method](); // 動的アクセス — tree shaking はどのメソッドが使われるか分からない
機能させる条件
1. ソースコードが ES モジュール(import/export)を使用している
2. webpack の mode が production
3. Babel が ES モジュールを CommonJS に変換していない
4. package.json の sideEffects が正しく設定されている
Babel が CommonJS に変換しないよう設定
javascript
// .babelrc または babel.config.js
{
"presets": [
["@babel/preset-env", {
"modules": false // 重要!CommonJS に変換しない
}]
]
}
sideEffects の設定
Webpack はどのファイルに副作用(CSS、polyfill など)があり、tree shake してはいけないかを知る必要があります:
json
// package.json
{
// すべてのファイルに副作用がない — 安全に tree shake できる
"sideEffects": false,
// または副作用のあるファイルをリストアップ
"sideEffects": ["*.css", "*.scss", "./src/polyfills.js"]
}
Tree Shaking が機能しているか検証
javascript
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
export function multiply(a, b) {
return a * b;
} // 使用しない
// main.js
import { add } from "./math";
console.log(add(1, 2));
本番ビルド後、multiply がバンドルに含まれていないことを確認します。webpack-bundle-analyzer で検証してください。
よくある問題
問題1:サードパーティライブラリに ES モジュール版がない
javascript
// lodash は CommonJS — tree shaking が機能しない
import { debounce } from "lodash"; // lodash 全体がバンドルされる!
// 解決策:lodash-es(ES モジュール版)を使用
import { debounce } from "lodash-es"; // ✅ debounce のみがバンドルされる
// またはパスで直接インポート
import debounce from "lodash/debounce"; // ✅ これも可
問題2:クラスの副作用
javascript
// クラスメソッドは通常 tree shake できない(副作用がある可能性があるため)
class Utils {
static add(a, b) {
return a + b;
}
static multiply(a, b) {
return a * b;
} // 使用していなくても含まれる可能性がある
}
// 関数としてエクスポートする形式に変更すると tree shaking の効果が高い
export function add(a, b) {
return a + b;
}
まとめ
- Tree shaking には ES モジュールが必要 — Babel は CommonJS に変換してはいけない
- package.json に
sideEffects: falseを設定する(副作用のあるファイルはリストアップする) webpack-bundle-analyzerで結果を検証するlodashをlodash-esに切り替えるとユーティリティライブラリの tree shaking が向上する