結局Webpackってなんのためにあるの？

# はじめに

JavaScript（フロントエンド）を始めてぶち当たるのが Webpack, Babel だと思います。（僕はぶち当たりました）
この記事では Webpack の使い方ではなく、 **「Webpack って結局なんのためにあって、あるとなんで嬉しいのか」** についてを書きます。
もし、間違っている、追記すべきことがあれば編集リクエストなどで教えていただけると幸いです。

# Webpack の役割

Webpack は下の記事にもある通り、 **モジュールバンドラー** と呼ばれるものです。

https://qiita.com/kamykn/items/45fb4690ace32216ca25

Webpack について全く知らないよって人はこの記事を読んでみると何をするものかはイメージがつくと思います。

簡単に説明すると、Webpack は **複数の JavaScript ファイルを 1 つにまとめてくれるもの** です。（JavaScript ファイル以外にも CSS とか画像ファイルもできます）

## 複数の`script`タグじゃだめなの？

HTML には複数の`script`タグを埋め込むことができ、複数の JavaScript ファイルを読み込むことができます。

例えば、以下のようなコードがあるとします。

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Sample Page</title>
  </head>
  <body>
    <script src="greets.js"></script>
    <script src="output.js"></script>
  </body>
</html>
```

```javascript:greets.js
const japanese = 'こんにちは';
```

```javascript:output.js
console.log(japanese);
```

この場合、ブラウザのコンソールには`こんにちは`と出力されます。
`greets.js`が先に読み込まれ、その後に`output.js`が読み込まれており、`output.js`内の`japanese`変数には`こんにちは`が入っているためです。

しかし、`index.html`が以下のような場合はどうでしょうか。

```html: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`が出力されます。

次に、それぞれのファイルで同じ変数名を定義した場合を見てみましょう。

```html:index.html
<!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>
```

```javascript:greets1.js
var japanese = 'こんにちは';
```

```javascript:greets2.js
var japanese = 'Konnichiwa';
```

```javascript:output.js
console.log(japanese);
```

この場合、コンソールには`Konnichiwa`が出力されます。
これは、ブラウザにはネームスペースが 1 つしかないため、`greets1.js`が読み込まれ、定義された`japanese`を`greets2.js`が読み込まれたときに **代入（上書き）されてしまう** ためです。（大人の事情により、`const`じゃなくて`var`を使ってます。気になる方は JavaScript の`var`の性質を調べてみると、あ〜となります。）

なにが言いたいのかというと、 **複数の JavaScript ファイルをロードする際には、読み込む順番や同じ変数名を使っていないかを確認する必要がある** ということです。
これを数十、数百ファイルで行うのは人間には不可能だと思います。

そこで出てくるのが **Webpack** です。

## `Webpack`を使うとどうなるの？

Webpack を使うことで、複数の script タグで JavaScript ファイルをロードするときに気をつけなければならないことを気にする必要がなくなります。

実際に Webpack を使った場合を見てみましょう。

```javascript:greets.js
const japanese = 'こんにちは';
export default japanese;
```

```javascript:index.js
import japanese from './greets';
console.log(japanese);
```

簡単に説明すると、`index.js`で`greets.js`の`japanese`変数をインポートして、それをコンソールに出力しています。
この`greets.js`と`index.js`を`Webpack`で 1 つのファイルにまとめるとこのようになります。

```javascript:main.js
(()=>{"use strict";console.log("こんにちは")})();
```

見やすくすると、

```javascript:main.js（見やすくしたもの）
(() => {
  "use strict";
  console.log("こんにちは")
})();
```

`console.log("こんにちは")`となっていることがわかります。
Webpack が`import / export`を解析し、必要なもの（今回の場合は`japanese`）を見つけ出し、コードを生成してくれているおかげで、JavaScript ファイルを読み込む順番を考える必要がなくなりました。

違うファイルで同じ変数名がある場合はどうでしょうか。

牛丼のテイクアウトの料金を出す`takeout.js`とイートインの料金を出す`eatin.js`を例にしたコードを考えます。`takeout.js`と`eatin.js`のコードは以下のようになりました。

```javascript:takeout.js
const gyudon = 350;
const tax = 1.08

export default gyudon * tax;
```

```javascript:eatin.js
const gyudon = 350;
const tax = 1.1

export default gyudon * tax;
```

```javascript:index.js
import takeout from './takeout';
import eatin from './eatin';

console.log('takeout', takeout);
console.log('eatin', eatin);
```

`script`タグで読み込んだ場合、変数名（`gyudon`, `tax`）が同じなため、上書き or エラーになりますが、Webpack だとどうでしょうか。
実際に、Webpack でまとめたコードは以下です。

```javascript:main.js
(()=>{"use strict";console.log("takeout",378),console.log("eatin",385.00000000000006)})();
```

例のごとく、見やすくします。

```javascript:main.js（見やすくしたもの）
(() => {
  "use strict";
  console.log("takeout", 378), console.log("eatin", 385.00000000000006)
})();
```

ちゃんとテイクアウト、イートインでの料金が計算されていることがわかります。
これは、Webpack がファイルごとに**ネームスペース**を区切っているため、異なるファイルで同じ変数名を使っても混ざることなくコードが生成されます。

気をつけなければならないことがなくなったので、複数の`script`タグを使って JavaScript ファイルをロードするときに比べ、開発がしやすくなったのではないでしょうか。

# まとめ

Webpack を使う前は、ブラウザのネームスペースが 1 つしかなく、複数の`script`タグを使うと **ロードの順序や変数名を気にして開発しなければなりません** でした。しかし、Webpack を使うことによって **ネームスペースの問題や、ロードの順序を気にする必要がなくなり** 、開発がしやすくなります。
規模の小さい場合だと、恩恵をあまり受けることができないかもしれませんが、規模が大きくなってくると確実に Webpack の恩恵を受けることができると思います。

今回は Webpack のお話でしたが、モジュールバンドラーには[Rollup](https://rollupjs.org/guide/en/)などもあるので、そちらも見てみると良いかもしれません。
また、Webpack は JavaScript だけでなく、CSS や画像などもまとめることができるので、それに挑戦してみたりすると、より Webpack について知れると思います。

# おまけ

最近のブラウザだと以下のようにモジュールに対応しているものがあります。
（「ESModule ブラウザ」とかで調べると出てきます）

[![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/eea90b65-6538-de50-461f-9119e8f60905.png)](https://caniuse.com/?search=esmodule)

実際にコードを書くと以下のようになります。

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <title>Sample Page</title>
  </head>
  <body>
    <script src="index.js" type="module"></script>
  </body>
</html>
```

```javascript:index.js
import japanese from './greets.js';
console.log(japanese);
```

```javascript:greets.js
const japanese = 'こんにちは';
export default japanese;
```

ただ、現段階では Webpack などのモジュールバンドラーを使ってバンドルするのが無難だと僕は思います。

# リンク

https://caniuse.com/?search=esmodule