はじめに
JavaScript(フロントエンド)を始めてぶち当たるのが Webpack, Babel だと思います。(僕はぶち当たりました)
この記事では Webpack の使い方ではなく、 「Webpack って結局なんのためにあって、あるとなんで嬉しいのか」 についてを書きます。
もし、間違っている、追記すべきことがあれば編集リクエストなどで教えていただけると幸いです。
Webpack の役割
Webpack は下の記事にもある通り、 モジュールバンドラー と呼ばれるものです。
Webpack について全く知らないよって人はこの記事を読んでみると何をするものかはイメージがつくと思います。
簡単に説明すると、Webpack は 複数の JavaScript ファイルを 1 つにまとめてくれるもの です。(JavaScript ファイル以外にも CSS とか画像ファイルもできます)
複数のscriptタグじゃだめなの?
HTML には複数のscriptタグを埋め込むことができ、複数の JavaScript ファイルを読み込むことができます。
例えば、以下のようなコードがあるとします。
<!DOCTYPE html>
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<script src="greets.js"></script>
<script src="output.js"></script>
</body>
</html>
const japanese = 'こんにちは';
console.log(japanese);
この場合、ブラウザのコンソールにはこんにちはと出力されます。
greets.jsが先に読み込まれ、その後にoutput.jsが読み込まれており、output.js内のjapanese変数にはこんにちはが入っているためです。
しかし、index.htmlが以下のような場合はどうでしょうか。
<!DOCTYPE html>
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<script src="output.js"></script>
<script src="greets.js"></script>
</body>
</html>
output.jsとgreets.jsの順番が逆になっています。
この場合、outputs.jsのjapanese変数はまだ定義されていないため、コンソールにundefinedが出力されます。
次に、それぞれのファイルで同じ変数名を定義した場合を見てみましょう。
<!DOCTYPE html>
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<script src="greets1.js"></script>
<script src="greets2.js"></script>
<script src="output.js"></script>
</body>
</html>
var japanese = 'こんにちは';
var japanese = 'Konnichiwa';
console.log(japanese);
この場合、コンソールにはKonnichiwaが出力されます。
これは、ブラウザにはネームスペースが 1 つしかないため、greets1.jsが読み込まれ、定義されたjapaneseをgreets2.jsが読み込まれたときに 代入(上書き)されてしまう ためです。(大人の事情により、constじゃなくてvarを使ってます。気になる方は JavaScript のvarの性質を調べてみると、あ〜となります。)
なにが言いたいのかというと、 複数の JavaScript ファイルをロードする際には、読み込む順番や同じ変数名を使っていないかを確認する必要がある ということです。
これを数十、数百ファイルで行うのは人間には不可能だと思います。
そこで出てくるのが Webpack です。
Webpackを使うとどうなるの?
Webpack を使うことで、複数の script タグで JavaScript ファイルをロードするときに気をつけなければならないことを気にする必要がなくなります。
実際に Webpack を使った場合を見てみましょう。
const japanese = 'こんにちは';
export default japanese;
import japanese from './greets';
console.log(japanese);
簡単に説明すると、index.jsでgreets.jsのjapanese変数をインポートして、それをコンソールに出力しています。
このgreets.jsとindex.jsをWebpackで 1 つのファイルにまとめるとこのようになります。
(()=>{"use strict";console.log("こんにちは")})();
見やすくすると、
(() => {
"use strict";
console.log("こんにちは")
})();
console.log("こんにちは")となっていることがわかります。
Webpack がimport / exportを解析し、必要なもの(今回の場合はjapanese)を見つけ出し、コードを生成してくれているおかげで、JavaScript ファイルを読み込む順番を考える必要がなくなりました。
違うファイルで同じ変数名がある場合はどうでしょうか。
牛丼のテイクアウトの料金を出すtakeout.jsとイートインの料金を出すeatin.jsを例にしたコードを考えます。takeout.jsとeatin.jsのコードは以下のようになりました。
const gyudon = 350;
const tax = 1.08
export default gyudon * tax;
const gyudon = 350;
const tax = 1.1
export default gyudon * tax;
import takeout from './takeout';
import eatin from './eatin';
console.log('takeout', takeout);
console.log('eatin', eatin);
scriptタグで読み込んだ場合、変数名(gyudon, tax)が同じなため、上書き or エラーになりますが、Webpack だとどうでしょうか。
実際に、Webpack でまとめたコードは以下です。
(()=>{"use strict";console.log("takeout",378),console.log("eatin",385.00000000000006)})();
例のごとく、見やすくします。
(() => {
"use strict";
console.log("takeout", 378), console.log("eatin", 385.00000000000006)
})();
ちゃんとテイクアウト、イートインでの料金が計算されていることがわかります。
これは、Webpack がファイルごとにネームスペースを区切っているため、異なるファイルで同じ変数名を使っても混ざることなくコードが生成されます。
気をつけなければならないことがなくなったので、複数のscriptタグを使って JavaScript ファイルをロードするときに比べ、開発がしやすくなったのではないでしょうか。
まとめ
Webpack を使う前は、ブラウザのネームスペースが 1 つしかなく、複数のscriptタグを使うと ロードの順序や変数名を気にして開発しなければなりません でした。しかし、Webpack を使うことによって ネームスペースの問題や、ロードの順序を気にする必要がなくなり 、開発がしやすくなります。
規模の小さい場合だと、恩恵をあまり受けることができないかもしれませんが、規模が大きくなってくると確実に Webpack の恩恵を受けることができると思います。
今回は Webpack のお話でしたが、モジュールバンドラーにはRollupなどもあるので、そちらも見てみると良いかもしれません。
また、Webpack は JavaScript だけでなく、CSS や画像などもまとめることができるので、それに挑戦してみたりすると、より Webpack について知れると思います。
おまけ
最近のブラウザだと以下のようにモジュールに対応しているものがあります。
(「ESModule ブラウザ」とかで調べると出てきます)
実際にコードを書くと以下のようになります。
<!DOCTYPE html>
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<script src="index.js" type="module"></script>
</body>
</html>
import japanese from './greets.js';
console.log(japanese);
const japanese = 'こんにちは';
export default japanese;
ただ、現段階では Webpack などのモジュールバンドラーを使ってバンドルするのが無難だと僕は思います。
リンク
