webpackは何をするものなのか

今までJSフレームワークを扱うときは特に深く考えずにwebpackを見よう見まねで使っていたが、業務で開発プロセスの改善について考えることになり、webpackの役割についてちゃんと理解しなければいけないことになった。
webpackの細かい機能は都度覚えていくしかないが、「何をするものなのか」はいろいろ調べて理解が深まったのでまとめておく。

webpackとはなにか

静的なasset(CSS, JS, 画像, フォントなど)をビルドしてバンドルするためのもの。バンドルとは平たく言うとひとつにまとめること。
静的なassetというのは、リクエストによって内容が変わったりしないファイルのこと。HTMLは、JSからDOMを操作されて内容が書き換えられたうえで返されることもあるが、CSSやJSの内容が書き換えられることはない。

webpack公式のトップページにあるこの図が全てを表している。

f:id:Udomomo:20180617124212p:plain

大規模な開発をするときは、require()などを使って、モジュールごとにファイルを分離して書くとわかりやすい。
しかし、ブラウザ上で動くJSはモジュール分割に対応しておらず、このままでは動かない。
そこで、webpack等のビルドツールを使うことで、モジュール同士の依存関係をふまえたうえでファイルをまとめてくれる。ファイルサイズが小さくなるようにminifyもしてくれる。
HTMLWebpackPluginを使うと、バンドルしたJSを読み込むHTMLも生成される。テンプレートがあればそれをもとにすることも可能。
あとはビルドで吐き出されたファイルとHTMLをサーバにアップロードすれば、開発中に想定していたとおりの動きをする。

また、webpackではJS以外の静的assetも管理できる。そのため、JSだけでなくCSSや画像などを読み込むときもrequire()を使って簡単に書くことができる。
例えば画像なら<img src={ require('../../assets/logo.png') } />などのように書ける。

静的assetを管理できると何がよいか?

まず、静的assetの過不足がなくなる。ビルドに使われるのは、コード内でrequire()されているもののみであるため、使わないassetが排除される。
逆に、JSは変えたがCSSが古いままだった・画像がリンク切れだったというようなことも起こらない。もしそのようなものがあれば、ビルドが通らないので本番公開前に気づくことができる。

また、静的assetをどう読み込むかもコントロールできるようになる。例えばbase64エンコードをかけて読み込んだり、サイズが大きければビルドに含めずwebpack外のURLから読み込む形にするなどの設定もでき、静的assetを柔軟に扱いやすくなる。

開発用サーバも立てられる

フロントエンド開発でネックになるのは、ビルドしないとブラウザ上で動かないこと。
動作確認をするのに、毎回npm run buildしてサーバにアップロードしなければいけないのでは面倒すぎる。

そこでwebpackでは、ローカルに簡単なサーバを立てる機能も提供されている。よく使われているのはwebpack-dev-server。
ローカルでの開発のための、小さなexpress製アプリである。localhost:8080/assets/bundle.jsのように指定すれば、すぐにそのファイルを擬似的にデプロイして確認できる。 watchの設定をすれば、ローカルサーバが立っている状態でファイルを更新すると、自動でコンパイルし直して画面に反映してくれる。
また、webpack-dev-serverサーバサイドとAPIで通信させたいときは、proxyの設定でリクエストを送るURLとサーバサイドのURLを対応させることができる。

webpackは今後も必要か?

ECMA2015では標準仕様としてモジュールが使えるようになったため、今後はブラウザ上でもモジュール分割を使えるようになっていき、webpackなどを使わなくてもよくなる場面が増えるかもしれない。
とはいえ、TypeScriptを使って開発する場合など、webpackがあった方が開発な楽なケースはまだまだあるだろう。
この辺りの話は以下のページがわかりやすい。

ics.media