webpackを使ってみる
前回、Babelについて書きました。
今回はwebpackの使い方をメモ程度のクオリティで書いていきます。
webpackとはなにか
モジュールバンドラというものです。
モジュールバンドラとは複数のJavaScriptファイルをまとめて1つのファイルにするツールのことです。
複数のJavaScriptファイルを1つにまとめると、どんな良いことがあるでしょうか?
- jsファイルの読み込み順など気にしなくても勝手に依存関係を解決してファイルをまとめてくれる。恐らくこれが1番のメリット。
- ファイルをまとめることでリクエスト数を減らす。通信回数を減らすことができる。
- 実行時は1つにまとめるので、気にせず機能ごとにファイルを分割してコーディングできる。 変数名が被っても大丈夫。
などなど、メリットがあります。
ディレクトリ構造
今回は以下のようなディレクトリ構造で進めていきます。
. ├── src │ ├── app.js │ ├── factorial.js │ └── fizzbuzz.js │ ├── dist │ └── bundle.js ├── node_modules ├── package.json └── webpack.config.js
webpackの環境構築
以下の環境でやってきます。
$ node --version v10.15.0 $ npm --version 6.5.0
まずはpackage.jsonを作ります。
npm init -y
必要なパッケージをインストール。
npm install --save-dev webpack webpack-cli
webpack.config.js
というwebpackの設定ファイルを作ります。
const path = require('path'); module.exports = { mode: 'development', entry: './app.js', output: { filename: 'bundle.js', path: path.join(__dirname, 'dist') }, };
- mode:
development
,production
,none
がある。development
: 開発用。ビルド時間が短い。production
: 本番用。ビルド時間が長い。最小化されたファイルが出力される。none
: オプション無効。
- entry: エントリーポイントの設定。起点となるjsファイルを指定する。 webpackはこのファイルが依存しているモジュールを調べてバンドル(まとめる)してくれる。
- filename: 出力ファイル名
- path: 出力先のパス
これで最低限のwebpackの環境ができました。
サンプルのコード
バンドルするJavaScriptを用意します。
サンプルでfizzbuzzと階乗を求めるモジュールを作りました。
これをapp.js
上で呼び出します。
fizzbuzz.js
export const fizzbuzz = x => { let result = ''; if (x % 3 == 0) result += 'Fizz'; if (x % 5 == 0) result += 'Buzz'; return result || x; };
factorial.js
export const factorial = x => { if (x === 0) return 1; return x * factorial(x - 1); };
app.js
import {fizzbuzz} from './fizzbuzz'; import {factorial} from './factorial'; console.log(fizzbuzz(3)); console.log(fizzbuzz(5)); console.log(fizzbuzz(15)); console.log(fizzbuzz(98)); console.log(factorial(5));
バンドルしてみる
npxコマンドを使用してwebpackを実行します。
npx webpack
npxが使えない環境は
./node_modules/.bin/webpack
実行結果
$ npx webpack Hash: 9ca0da58fd666451390a Version: webpack 4.29.6 Time: 99ms Built at: 03/21/2019 12:07:03 AM Asset Size Chunks Chunk Names bundle.js 5.62 KiB main [emitted] main Entrypoint main = bundle.js [./app.js] 211 bytes {main} [built] [./factorial.js] 107 bytes {main} [built] [./fizzbuzz.js] 156 bytes {main} [built]
特にエラーがなければdist
フォルダの中に1つにまとめられたbundle.js
ができています。
bundle.js実行
$ node dist/bundle.js Fizz Buzz FizzBuzz 98 120
app.js
上で呼び出したモジュールがまとめられ、ちゃんと実行できています。
webpack&Bebelで使う
次にwebpackとBabelと組み合わせて使ってみます。
必要なパッケージのインストール
$ npm install --save-dev babel-loader @babel/core @babel/preset-env
- babel-loader: webpackでBabelを使うのに必要なパッケージ
webpack.config.js
を以下のように書き換えます。
const path = require('path'); module.exports = { mode: 'development', entry: './src/app.js', output: { filename: 'bundle.js', path: path.join(__dirname, 'dist') }, // ↓以下追加 module: { rules: [ { // 処理対象ファイル test: /\.m?js$/, // 処理の対象外にするディレクトリ exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: ['@babel/preset-env'] } } } ] } };
module
というのを追加しました。
ここは「jsファイルはBabelで変換するように。ただし、node_modulesディレクトリ内のjsファイルは無視してね。」という指示を書いています。
node_modulesを除外しないと変換の速度が遅くなったり、エラーになったりするようです。
Babelの設定はbabel.config.js
などに書くのですが、webpack.config.js
のoptions
に書いてしまうこともできます。今回はこっちに設定を書きました。
Babelとwebpackを連携させる設定ができたので、
あとはwebpackを実行すればトランスパイルされているbundle.js
が出力されます。
modeをnoneにすると変換したところがわかりやすいのでnoneで実行します。
$ npx webpack --mode=none
bundle.jsの中身抜粋
/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "fizzbuzz", function() { return fizzbuzz; }); var fizzbuzz = function fizzbuzz(x) { var result = ''; if (x % 3 == 0) result += 'Fizz'; if (x % 5 == 0) result += 'Buzz'; return result || x; }; /***/ }), /* 2 */ /***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict"; __webpack_require__.r(__webpack_exports__); /* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "factorial", function() { return factorial; }); var factorial = function factorial(x) { if (x === 0) return 1; return x * factorial(x - 1); }; /***/ }) /******/ ]);
わざとらしくアロー関数で書いたとこがトランスパイルされているのを確認できました!
おわり。