webpackとは
webPackとはモジュールバンドラと呼ばれるツールです。アプリーケーションが依存するjsモジュールを一つのjsファイルにまとめ上げ、依存関係の解決やトランスパイルを自動実行してくれます。内部的にモジュール同士の依存関係を表すグラフを自動で構築し、それに基づいて依存関係の解決をしてくれるので、設定ファイルなどなしに使用することができます(詳細な設定を記述したファイルを使用することもできます)。
・・・とはいったものの、「モジュールのバンドル」がいまいちピンと来なかったので、こちらのチュートリアルを実践してみました。
以下、チュートリアルのメモになります。
webpackのインストール
まず、webpack対象となる node
プロジェクトを作成します。
$ mkdir hello-webpack $ cd hello-webpack $ npm init -y
npm
でwebpackと、webpackのCLIツールをインストールします。
$ npm install webpack webpack-cli --save-dev
webpackを試しに使用する
実験環境準備
webpackを使用する前に、テスト用のモジュールを作ってみます。
最初のディレクトリ構成は以下の通り。
$ ls node_modules package.json package-lock.json
プロジェクトルートに以下のような index.html
を作成します。HTMLを見ると、 index.html
は <script>
タグ中でCDNによって茶刈 lodash.js
スクリプトをロードしていることがわかります。
<!doctype html> <html> <head> <title>Hello, webpack !!1!</title> <script src="https://unpkg.com/lodash@4.16.6"></script> </head> <body> <script src="./src/index.js"></script> </body> </html>
次に内部ロジック記述用スクリプトである src/index.js
を用意します。このスクリプトでは、先程 index.html
でロードしていた lodash
モジュールを使用しようとしているとします。が、 lodash
に対する依存関係が暗黙的で、 _
を未定義のグローバル変数として参照してしまっています。
function component() { let element = document.createElement('div'); element.innerHTML = _.join(['Hello', 'webpack'], ' '); return element; } document.body.appendChild(component());
上記の index.js
のような、参照できているようで参照できていない暗黙の依存関係は様々なバグを生んでしまいます。
このようなバグをなくすため、lodash
をnpmでのパッケージインストール & import に変更してしまいましょう!
npm での lodash
のインストール
先程用意した index.html
を、新たに生成した /dist
ディレクトリ配下に配置します。
dist └── index.html
次に、 lodash
をnpm経由でインストール。
$ npm install --save lodash
src/index.js
を修正します。明示的に lodash
を参照できるよう、下記一文をファイル先頭に追加します。
import _ from 'lodash';
dist/index.html
を編集します。
<script>
タグによる lodash
のロードをやめ、 参照先スクリプトを main.js
としました。これは後ほど使用するwebpackのバンドル後ファイルへの参照です。
webpackによるモジュールバンドル
上記の import
文によって、webpackが依存関係のグラフを自動作成可能になりました。
それでは、実際にwebpackでモジュールバンドルを行います。
npx
コマンドを使用し、 webpack
を実行します。
npx
についてはこちらを参照。
$ npx webpack Hash: 53680323beef520a74cd Version: webpack 4.28.2 Time: 445ms Built at: 2018/12/25 23:10:03 Asset Size Chunks Chunk Names main.js 1.03 KiB 0 [emitted] main Entrypoint main = main.js [0] ./src/index.js 189 bytes {0} [built] WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
webpackが成功し、 dist/main.js
が生成されました!
!function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t){document.body.appendChild(function(){let e=document.createElement("div");return e.innerHTML=_.join(["Hello","webpack"]," "),e}())}])
どうやら「モジュールのバンドル」 とは
- 依存モジュールを一つの
js
にまとめること - スクリプトのミニマイズもする
- トランスパイルもする
といった操作のようです。
webpackを使ってみての感想ですが、「アプリの最適化」を行うのには素晴らしいツールだなと思いました。 アプリの複雑な依存関係を解決し一つのファイルにアプリのスクリプトをまとめることで、ビルド・デプロイするアプリを軽量化・高速化できるので、アプリの総仕上げとして良いのではないでしょうか。 (多くのフロントエンドCLIでもデフォルトで採用されているみたいですね)