Tree Shaking の仕組み

Tree Shaking は、使用されていないコード(デッドコード)をバンドルから除外する最適化技術です。これにより、最終的なバンドルサイズを小さくできます。

Tree Shaking とは

木を揺すると(shake)、枯れ葉(使われないコード)が落ちるイメージから名付けられました。

// utils.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 './utils.js';
console.log(add(2, 3));
// subtract と multiply は使われていない

Tree Shaking により、subtract と multiply はバンドルに含まれません。

なぜ ES Modules が必要か

Tree Shaking は、ES Modules の静的構造に依存しています。

ES Modules(静的)

import/export は静的に解析可能。使用される関数を事前に特定できる。

CommonJS(動的)

require は動的に実行される。何が使われるか実行時まで分からない。

// CommonJS - Tree Shaking が効かない
const utils = require('./utils');
// utils のどのプロパティが使われるか静的に判断できない

バンドラーでの動作

Webpack、Rollup、Vite などのバンドラーが Tree Shaking を実行します。

// 元のコード
import { add } from './utils.js';
console.log(add(2, 3));

// Tree Shaking 後のバンドル(イメージ)
function add(a, b) {
  return a + b;
}
console.log(add(2, 3));
// subtract, multiply は含まれない

効果的な書き方

Tree Shaking を最大限活用するためのベストプラクティスです。

名前付きエクスポートを使う

default export よりも named export の方が Tree Shaking が効きやすい。

サイドエフェクトを避ける

モジュールのトップレベルで副作用のあるコードを書かない。

// 良い例:名前付きエクスポート
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }

// 避けるべき例:サイドエフェクト
console.log('Module loaded'); // これがあると削除されにくい
export function add(a, b) { return a + b; }

sideEffects フィールド

package.json で、モジュールにサイドエフェクトがないことを明示できます。

{
  "name": "my-library",
  "sideEffects": false
}

特定のファイルだけサイドエフェクトがある場合は配列で指定します。

{
  "name": "my-library",
  "sideEffects": [
    "./src/polyfill.js",
    "*.css"
  ]
}

Tree Shaking が効かない場合

CommonJS モジュールを使用している
動的インポート import() の結果を動的に使用
オブジェクトとしてまとめてエクスポート
サイドエフェクトがあるモジュール
// Tree Shaking が効かない例

// 1. オブジェクトでまとめてエクスポート
const utils = {
  add: (a, b) => a + b,
  subtract: (a, b) => a - b
};
export default utils; // utils.add を使っても subtract も含まれる

// 2. 動的なプロパティアクセス
import * as math from './math.js';
const fn = math[functionName]; // 静的に解析できない

確認方法

Webpack では、バンドル分析ツールで Tree Shaking の効果を確認できます。

# webpack-bundle-analyzer でバンドルを可視化
npm install --save-dev webpack-bundle-analyzer
// webpack.config.js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
};

Tree Shaking を意識したコードを書くことで、アプリケーションのパフォーマンスを向上させることができます。