こんにちは!フロントエンド開発の現場で、日々コードを書いたりビルドの最適化に頭を悩ませたりしていませんか?
「なんだか最近、アプリの読み込み速度が遅い気がする……」
「ビルド後のJavaScriptファイル(バンドルサイズ)が、気づけば数メガバイトに膨れ上がっている……」
そんな壁にぶつかったとき、多くの人は「どのライブラリを削るべきか」と悩みます。しかし、真のアーキテクトは勘に頼りません。データを見ます。それが今回紹介する Webpackの『Statsデータ』 を使った最適化アプローチです。
今回は、Webpackが吐き出す内部データ(Stats JSON)を徹底的に解析し、「知らぬ間にアプリに紛れ込んでいた巨大な不要Polyfill(ポリフィル)」を特定して、バンドルサイズを劇的に削る技術を、優しく丁寧に解説していきます。
これをマスターすれば、あなたの作るWebアプリは見違えるほど軽くなり、ユーザー体験(UX)を最高レベルに引き上げることができますよ。さあ、一緒にプロの最適化術の世界へ足を踏み入れましょう!
—
1. Webpackの「Statsデータ」とは何か?(ツールの役割)
まず、「Stats(スタッツ)」という言葉の正体を押さえましょう。
Webpackは、私たちが書いたソースコードやCSS、画像などを読み込み、ブラウザが理解できるファイルへと「バンドル(束ねる)」してくれます。そのビルド処理の最中、Webpackの内部では「どのファイルからどのファイルへ依存しているか」「どのモジュールにどれくらいのバイト数が割かれているか」という、膨大なメタデータ(内部統計情報)が生成されています。
通常、このデータはコンソールにチラッと表示されるビルド結果(「Asset Size Modules」など)の裏側に隠されています。しかし、Webpackには、この内部データを丸ごとJSONファイルとして出力させる機能が備わっています。これが「Statsデータ」です。
なぜStatsデータが必要なのか?
「どのファイルが重いか」を視覚化するツール(例えば `webpack-bundle-analyzer` など)は有名ですが、それらのビジュアライザーも、突き詰めると内部的にはこのStats JSONを読み込んで描画しています。
つまり、Stats JSONの構造を理解し、自分でデータを抽出できるようになると、既存のツールでは見えない「ライブラリの依存関係の闇(なぜそのコードがバンドルに含まれてしまったのか)」を完全にコントロールできるようになるのです。
—
2. 最速で動かす!Statsデータ出力の基礎セットアップ
理屈はこれくらいにして、実際に手を動かしてみましょう。
ここでは、最小限のWebpack環境を用意し、Statsデータを出力するまでのステップを優しく解説します。
ステップ①:プロジェクトの初期化とパッケージのインストール
まずは作業用ディレクトリを作り、最低限のパッケージをインストールします。
プロジェクトディレクトリの作成と移動
mkdir webpack-stats-lab && cd webpack-stats-lab
npmの初期化
npm init -y
Webpack本体とCLIのインストール
npm install –save-dev webpack webpack-cli
ステップ②:動作確認用の「Hello World」コードを作る
次に、ビルドの元となるソースコードを用意します。モダンなJavaScript(ここではあえて古い環境を想定してBabel等を通すようなイメージ)を記述します。
srcディレクトリの作成
mkdir src
`src/index.js` を作成し、以下のコードを記述してください。
// src/index.js
// 現代のブラウザでは標準サポートされているPromiseやArray.prototype.includesあえて使用し、
// Polyfillが必要になる状況を擬似的に再現します。
const message = “Hello, Webpack Stats Lab!”;
const numbers = [1, 2, 3, 4, 5];
// includesメソッド(ES2016)
const hasThree = numbers.includes(3);
const asyncGreeting = async () => {
return `${message} (Has 3: ${hasThree})`;
};
asyncGreeting().then(console.log);
ステップ③:Webpack設定ファイル(`webpack.config.js`)の作成
ここが一番の核心です。Webpackに「ビルド結果のJSONを出力してくれ」と指示する設定を行います。
プロジェクトのルートに `webpack.config.js` を作成し、以下のように記述してください。
// webpack.config.js
const path = require(‘path’);
module.exports = {
// 開発モード(人間が読みやすいコード)
mode: ‘development’,
// エントリーポイント
entry: ‘./src/index.js’,
// アウトプット設定
output: {
filename: ‘bundle.js’,
path: path.resolve(__dirname, ‘dist’),
},
// ★ここが最重要:WebpackにStats(統計データ)をJSONとして出力させる設定
stats: {
colors: true,
reasons: true, // なぜそのモジュールがバンドルされたかの理由を出力に含める
modules: true, // モジュールの詳細を含める
assets: true, // アセット情報の出力
},
};
ステップ④:ビルドを実行してStats JSONを取り出す
コマンドラインから、Webpackを実行しつつ、その出力をJSONファイルとして保存します。
webpackコマンドを実行し、–profileオプションと–jsonフラグでファイルに出力する
npx webpack –profile –json=stats.json
実行が成功すると、プロジェクトのルートディレクトリに `stats.json` という巨大なファイルが生成されます。これが、あなたのアプリの通信簿、すなわち「Statsデータ」です!
—
3. 現場で震えるほど役立つ:Statsデータから「不要なPolyfill」を暴く技術
さて、生成された数万行に及ぶ `stats.json` を開いてみてください……と言いたいところですが、人間がテキストエディタで読むのは不可能に近いですよね。
ここで、プロが現場で使っている解析手法を伝授します。
「どのライブラリが、どのPolyfill(core-jsなど)を引っ張ってきているのか」をコマンド一発、あるいは小さなスクリプトで特定します。
Webpack公式のビジュアライザーを活用する
一番手っ取り早く、かつ美しいのは、Webpack公式が提供しているWebツール 「Webpack Visualizer」 や 「Webpack Bundle Analyzer」 に先ほどの `stats.json` を食わせることです。
今回は、ローカルで瞬時に依存関係のサイズをツリーマップ表示できる `webpack-bundle-analyzer` を使ってみましょう。
アナライザーをインストール
npm install –save-dev webpack-bundle-analyzer
`webpack.config.js` を少し書き換えて、ビルド時に自動で解析画面が開くようにします。
// webpack.config.js (追記版)
const path = require(‘path’);
// BundleAnalyzerPluginの読み込み
const BundleAnalyzerPlugin = require(‘webpack-bundle-analyzer’).BundleAnalyzerPlugin;
module.exports = {
mode: ‘development’,
entry: ‘./src/index.js’,
output: {
filename: ‘bundle.js’,
path: path.resolve(__dirname, ‘dist’),
},
plugins: [
// プラグインを追加することで、stats.jsonを視覚化するダッシュボードが立ち上がります
new BundleAnalyzerPlugin()
]
};
再度ビルドを実行してみます。
npx webpack
すると、ブラウザが自動的に立ち上がり、どのパッケージがバンドルの何パーセントを占めているかのカラフルな地図が表示されます。
ここで、もし `core-js` や `regenerator-runtime` といった見覚えのない巨大なPolyfillパッケージが陣取っていたら……それが犯人です。
—
4. なぜ不要なPolyfillが混入するのか?(原因と対策)
現代のWeb開発では、BabelやTypeScriptのトランスパイル設定(`target` や `browserslist`)が不適切なために、以下のような現象が起きます。
1. 「ひょっとしたらIE11も見ているかもしれない」とBabelが勘違いする。
2. 標準API(`Array.prototype.includes` や `Promise` など)に対して、ご丁寧に巨大なPolyfillコードを自動挿入する。
3. 結果として、最新のChromeやSafariを使っているユーザーに対しても、無駄に重いコードをダウンロードさせてしまう。
解決策:ターゲットブラウザを現代化する
もしあなたのサービスが「モダンブラウザ(Chrome, Safari, Edge, Firefoxの最新版など)」をターゲットにしているのであれば、トランスパイルの設定やWebpack/Babelのターゲットを明確に指定し直すだけで、これらの不要なPolyfillをごっそり削り落とすことができます。
例えば、プロジェクトに `package.json` の設定を追加し、ターゲットブラウザを絞り込みます。
// package.json の末尾などに追加
{
“browserslist”: [
“> 0.5%”,
“last 2 versions”,
“not dead”,
“not IE 11”
]
}
この設定をBabelやWebpack(SWCやViteなどを使う場合も同様です)に正しく認識させることで、「あ、IE11のサポートはもう必要ないんだな。じゃあ `Array.includes` のポリフィルは出力するのをやめよう」とビルドツールが判断し、バンドルサイズが劇的に軽くなります。
—
おわりに
お疲れ様でした!今回は、Webpackの「Statsデータ」の概念から、実際の出力、そしてビジュアライザーを用いた不要Polyfillの特定・最適化のステップまでを駆け足で解説しました。
開発現場において、「なんとなく重いからライブラリを削る」というアプローチから卒業し、「Statsデータという客観的な事実に基づき、不要なトランスパイルやPolyfillを外科手術のようにピンポイントで排除する」というアプローチを手に入れたあなたは、もうワンランク上のエンジニアです。
これをマスターすれば、毎日のビルド結果を見るのが少し楽しみになり、パフォーマンスチューニングの引き出しがグッと広がりますよ。ぜひ、あなたの実際のプロジェクトでも `stats.json` を出力して、思わぬ「お宝(不要な巨石コード)」を発見してみてくださいね。それでは、快適な開発ライフを!