webpackを使ったことのない人にとって最初につまづくものはbundle(バンドル)という単語かもしれません。bundleは束ねるという意味があるので、webpackは複数のファイルをまとめる処理(bundle your asset/image/scripts/styles)を行うツールだということが意識できればwebpackを理解するスピードも格段に上がります。ファイルをまとめるを念頭において読み進めてください。

webpackはnpmを使ってインストールを行うのでnpmがわからない人は以下の記事を参考にしてください。

webpackのインストール

npmを使用してインストールを行うためにディレクトリを作成します。ここでは動作確認用なのでtestというディレクトリを作成しています。


mac $ mkdir test
mac $ cd test

npm initコマンドでpackage.jsonファイルを作成します。


mac $ npm init -yes

パッケージを開発用としてインストールする場合は、–save-devをつけてnpm installコマンドを実行します。webpackとwebpackのコマンドラインインターフェイスであるwebpack-cliの2つパッケージをインストールします。webpack-cliをインストールしなければ、webpackを実行することはできません。


mac $ npm install --save-dev webpack webpack-cli

package.jsonが未作成の状態でinstallを行うとnpm listを実行するとnpm ERR! extraneous:が多数表示されます。package.jsonの作成を忘れないように進めてください。

インストール後、package.jsonを確認するとdeevDependenciesには、webpackとwebpack-cliの情報が下記のように追加されます。


  "devDependencies": {
    "webpack": "^4.31.0",
    "webpack-cli": "^3.3.2"
  }

以上でwebpackのインストールは完了です。

webpackコマンドの実行方法の確認

webpackどういった処理を行うか説明する前にwebpackコマンドの実行方法について説明を行います。

webpackコマンドをインストールディレクトリで実行した場合、PATH(パス)の設定が行われていなければcommand not foundエラーが表示されます。

※-vはwebpackのバージョンを表示させるオプションです。動作確認を行うためには-vオプションをつけて実行しています。


mac $ webpack -v
-bash: webpack: command not found

PATH(パス)がわからない人はこちらの文書を参考にしてください。

エラーが表示される理由は、インストールするパッケージの実行ファイルがnode_modules/.bin/の下に保存されるためです。webpackコマンドを実行するためには、下記のように実行ファイルの場所を指定する必要があります。


mac $ $ ./node_modules/.bin/webpack -v
4.31.0

その他にも実行方法には下記のようなものがあります。

  • npxコマンドを利用する方法
  • package.jsonのscriptsにコマンドを記述する方法

npxコマンドを利用した実行

npxコマンドを利用する場合は、npxの後にwebpackを指定すれば実行することができます。


mac $ npx webpack -v
4.31.0

npxを使うとPATHの設定が行われていなくてもnode_modules/.bin/ディレクトリの中から指定したコマンドを自動的に探し出して実行します。そのためPATHの設定を行う必要がありません。

package.jsonのscriptsに記述する方法

一般的には下記のようにpackage.jsのscriptsにコマンドを追加することでPATHを意識することなく実行することができます。


 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack -v"
  },

package.jsonに追加後、rpm run bulidを実行するとwebpack -vを実行することができます。


test $ npm run build

> test@1.0.0 build /Users/mac/Document/test
> webpack -v

4.31.0

webpackを実行する際に-vオプションは必要ないので、webpackコマンドの実行方法が確認できた後は、package.jsonは下記のように書き換えておきます。


 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },

webpackの実行

webpackコマンドの実行方法が確認できたので、実際にwebpackコマンドを実行して理解を深めていきます。


mac $ npm run build

実行するとWARNINGとERRORが下記のように出力されます。

※他にも実行ログが出力されますが、WANINGとERRORのみ抜粋しています。


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/configuration/mode/

ERROR in Entry module not found: Error: Can't resolve './src' in '/Users/mac/Document/test'

エントリーモジュールのERROR対応

ERRORについては./srcの中にエントリーモジュールを見つけることができないというエラーなので、srcディレクトリを作成し、その中にindex.jsファイルを作成します。index.jsの中身は空でかまいません。


mac $ mkdir src
mac $ cd src
mac $ touch index.js

再度npm run buildを実行します。Errorの表示が消え、WARNINGだけが残った状態になります。


test $ npm run build

> test@1.0.0 build /Users/mac/Document/test
> webpack

Hash: f938a17692d3bf136b01
Version: webpack 4.31.0
Time: 119ms
Built at: 2019-05-16 15:59:37
  Asset       Size  Chunks             Chunk Names
main.js  930 bytes       0  [emitted]  main
Entrypoint main = main.js
[0] ./src/index.js 0 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/configuration/mode/

実行後、新たにdistディレクトリ(distribution:配布)が作成され、その中にmain.jsが作成されることが確認できます。


mac $ ls
dist			package-lock.json	src
node_modules		package.json
mac $ ls dist
main.js

webpack初期のディレクトリ構成
webpack初期のディレクトリ構成

index.jsファイルがwebpackの処理の中で解析、処理された結果main.jsファイリルが作成されます。このmain.jsの元になるindex.jsファイルはエンドポイントと呼ばれwebpackの一連の処理の中でメインとなるJavaScriptファイルです。

初期設定では、webpackはsrcディレクトリにindex.jsがないかチェックを行い、あれば処理を行い、自動でdistディレクトリを作成し、処理のけっkけっk

これだけの処理では1つのファイル(index.js)から1つのファイル(main.js)が出来ただけですが、後ほど複数のファイルから1つのファイルへとまとめる処理を行います。

作成されたファイルmain.jsを下記のようにHTMLで指定して使います。


<script src="./dist/main.js"></script>

webpackではsrcディレクトリにindex.jsファイルさえあれば設定ファイルなしで処理を行うことができます

modeオプションのWARNINGへの対応

webpack実行時に出力されていたWARNINGに対応するためにmode(モード)の設定を行います。modeにはproduction, development, noneを設定することが可能です。productionモードではファイルを圧縮するなどdevelopmentと大きな違いがあります。以下のようにpackage.jsonのscriptsで分けることで開発と本番用を分けることも可能です。


  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development",
    "build": "webpack --mode production"
  },

この設定により、npm runでdevを指定した場合はmodeはdevelopment, buildを指定した場合は、modeはproductionで実行されます。

ここまでの設定を行うことでwebpack実行時のエラーと警告はなくなります。


mac $ npm run build

> test@1.0.0 build /Users/mac/Document/test
> webpack --mode production

Hash: a7ab55fd5d9673cb0317
Version: webpack 4.31.0
Time: 122ms
Built at: 2019-05-16 21:39:15
  Asset       Size  Chunks             Chunk Names
main.js  930 bytes       0  [emitted]  main
Entrypoint main = main.js
[0] ./src/index.js 0 bytes {0} [built]

watchオプションで変更を監視

javascriptを変更する回数が多く変更毎にnpm runコマンドを実行するが大変な場合にはwatchオプションを使います。watchオプションは、jsファイルの変更を監視することができるのでjsファイルに変更があると自動でnpm runコマンドを実行してくれます。

<pre data-title="javascript"><code class="code-break language-javasciprt">
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack --mode development",
    "build": "webpack --mode production",
    "watch": "webpack --mode development --watch"
  },
</code>
</pre>

scriptsにwatchを追加したら、npm run watchコマンドを実行し、別のコンソールを起動もしくはエディターでjsファイルを変更を行ってください。自動でnpm run watchコマンドが実行されます。

webpackで複数のファイルをまとめる

ERROR, WARNINGも出力されなくなり、最もシンプルな方法でのwebpackコマンドの使用方法がわかりました。ここから実際に複数のファイルをまとめる処理を行います。

ファイルをまとめる準備

index.htmlファイルを作成します。まずscriptタグには、index.jsを指定します。


<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>webpack</title>
	<script src="src/index.js"></script>
</head>
<body>
	
</body>
</html>

index.jsにもconsole.logを記述します。


console.log('Hello World')

index.htmlをブラウザで開き、ConsoleにHello Worldが表示されることを確認します。

コンソールにHello World
コンソールにHello World

webpackの処理を行うため、npm run devを実行します。正常に終了できたら、先ほどのindex.htmlのscriptタグの指定をindex.jsからdst/main.jsに変更し、ConsoleにHello Worldが表示されることを確認します。


mac $ npm run build

> test@1.0.0 dev /Users/reffect/Desktop/test
> webpack --mode development

Hash: 2de7563477518cf0bba0
Version: webpack 4.31.0
Time: 120ms
Built at: 2019-05-18 10:26:23
  Asset      Size  Chunks             Chunk Names
main.js  3.79 KiB    main  [emitted]  main
Entrypoint main = main.js
[./src/index.js] 26 bytes {main} [built]


<script src="dist/main.js"></script>

複数のファイルをまとめる処理

2つの数字を合計する関数を含むsum.jsと2つの数字を掛け合わせるmultiply.jsの2つのファイルを用意して、index.jsファイルから読み込めるようにします。

javascriptではsum.js, multiply.jsこの1つ1つのファイルのことをモジュールと呼びます。

export default function sum(a,b) {

return a + b;

}

export default function multiply(a,b) {

return a * b;

}

index.js内で2つのファイルを読み込み、その結果をconsoleに出力させます。


import sum from './sum.js';

import multiply from './multiply.js';

var num1 = 10;

var num2 = 5;

var result = '合計は' + sum(num1,num2) + ',掛け算は' + multiply(num1,num2);

console.log(result);

これまではindex.jsのファイルからwebpackを通して1つのファイルを作成してきましたが、今回は、index.js, sum.js, multply.jsの3つのファイルが関連する処理になっています。

npm run devを実行します。実行のログにも3つのファイルの情報が出力されていることがわかります。


mac $ npm run dev

> test@1.0.0 dev /Users/mac/Document/test
> webpack --mode development

Hash: d13dfa8042f4879b4a42
Version: webpack 4.31.0
Time: 129ms
Built at: 2019-05-18 10:47:15
  Asset     Size  Chunks             Chunk Names
main.js  5.3 KiB    main  [emitted]  main
Entrypoint main = main.js
[./src/index.js] 183 bytes {main} [built]
[./src/multiply.js] 57 bytes {main} [built]
[./src/sum.js] 52 bytes {main} [built]

ブラウザでindex.htmlファイルを確認します。scriptタグで指定するはindex.jsファイルではなくmain.jsだというのを忘れないようにしてください。


<script src="dist/main.js"></script>

ブラウザのconsoleには、合計は15, 掛け算は50が表示されます。

sumとmultiplyの結果表示
sumとmultiplyの結果表示

module.exportとexport, requireとimportの違い

入門者にとって混乱するのがあるところではexportと記載があり、あるところではmodule.exportと記載がありどちらが正しいのかという疑問です。webpackではどちらでも問題なく動作します。

multiply.jsのみ書き方をmodule.exportsに変更してみましょう。


module.exports = function(a,b) {

return a * b;

};

index.jsもimportからrequireに変更を行います。


import sum from './sum.js';

var multiply = require('./multiply');

var num1 = 10;

var num2 = 5;

var result = '合計は' + sum(num1,num2) + ',掛け算は' + multiply(num1,num2);

console.log(result);

2つの構文を混ぜても正常に動作することが確認できます。

modeの設定によるmain.jsファイルの違い

webpackを実行する際にmodeの設定ができることは説明済みですが、作成されるmain.jsの中身を確認します。

mode=developmentで実行した場合のmain.jsファイルは下記のようになります。(一部の抜粋)


/******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

mode=productionで実行した場合のmain.jsファイルは下記のようになります。(一部の抜粋)


!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].

ファイルを見ただけで圧縮されていることも確認できます。

webpack 4ではmodeをproductionにするとoptimization(最適化)の設定が行われます。圧縮にはTeserPluginを利用して圧縮が行われるようです。

Chart.jsライブラリを使う

ここまでは、単純な自作のjavascriptファイルのみを扱ってきましたが、今度はChart.jsライブラリをwebpackで読み込んで使えるのか確認しておきます。

npmでchart.jsライブラリをインストールします。


test $ npm install chart.js
npm WARN test@1.0.0 No description
npm WARN test@1.0.0 No repository field.

+ chart.js@2.8.0
added 5 packages from 7 contributors and audited 5237 packages in 5.148s
found 0 vulnerabilities

index.htmlでチャートを表示するためのcanvasタグを入れます。


<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>Chart.jsを使ってみる</title>
	<script src="dist/main.js"></script>
</head>
<body>

	<canvas id="myChart" width="400" height="400"></canvas>
	
</body>
</html>

index.jsではインストールしたchart.jsをインポートしてバーチャートを表示させるコードを追加しています。コードはchart.jsのサイトのサンプルを利用しています。


import Chart from 'chart.js';

window.onload=function(){
var ctx = document.getElementById('myChart').getContext('2d');
	var myChart = new Chart(ctx, {
	    type: 'bar',
	    data: {
	        labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
	        datasets: [{
	            label: '# of Votes',
	            data: [12, 19, 3, 5, 2, 3],
	            backgroundColor: [
	                'rgba(255, 99, 132, 0.2)',
	                'rgba(54, 162, 235, 0.2)',
	                'rgba(255, 206, 86, 0.2)',
	                'rgba(75, 192, 192, 0.2)',
	                'rgba(153, 102, 255, 0.2)',
	                'rgba(255, 159, 64, 0.2)'
	            ],
	            borderColor: [
	                'rgba(255, 99, 132, 1)',
	                'rgba(54, 162, 235, 1)',
	                'rgba(255, 206, 86, 1)',
	                'rgba(75, 192, 192, 1)',
	                'rgba(153, 102, 255, 1)',
	                'rgba(255, 159, 64, 1)'
	            ],
	            borderWidth: 1
	        }]
	    },
	    options: {
	        scales: {
	            yAxes: [{
	                ticks: {
	                    beginAtZero: true
	                }
	            }]
	        }
	    }
	});
}

ブラウザで確認するとバーチャートが表示されます。

chartjsでバーチャートを表示
chartjsでバーチャートを表示

他のライブラリを使いたい場合も同様の方法で行うことができます。

webpackの他の設定方法について下記の文書で公開しています。