Webpack Level 2: 設定ファイルをカスタマイズする

前回「[裸のWebpackのデフォルト動作を理解する](https://qiita.com/takano-h/items/3240181a83ef5e6f26a6)」に引き続き、設定ファイルについて理解してみたいと思います。

## コンテンツ
- [Webpack Level 1: 裸のWebpackのデフォルト動作を理解する](https://qiita.com/takano-h/items/3240181a83ef5e6f26a6)
- [Webpack Level 2: 設定ファイルをカスタマイズする](https://qiita.com/takano-h/items/a0c6783c79fa38c50673)
- [Webpack Level 3: loadersを追加して.js以外のファイルを結合する](https://qiita.com/takano-h/items/1a6a5a0b9d25a677f7d2)
- [Webpack Level 4: Webpack Pluginsを用いて静的サイトをS3に自動デプロイ](https://qiita.com/takano-h/items/abd3fca1514767468878) <- 今ここ

## 環境
- webpack 4.16.3
- webpack-cli 3.1.0
- webpack-dev-server 3.1.5

## 設定ファイルの位置を変更する
Webpackの設定ファイル `webpack.config.js` は、デフォルトではプロジェクトのルート位置にあることが期待されていますが、コマンド実行時のオプションによって位置を変更することができます。
開発環境と本番環境でWebpackの設定を使い分けたい時など、設定ファイルが複数ある場合はプロジェクトのルートではなく `config` ディレクトリなどにまとめておきたいですよね。そういった場合、例えば下記のようにファイルを配置してコマンドを実行します。

```javascript:src/index.js
console.log('Hello, webpack.');
```

```javascript:config/webpack-dev.config.js
module.exports = {
  mode: 'development',
};
```

```bash
$ webpack --config config/webpack-dev.config
```

無事にバンドル結果が `dist/bundle.js` に吐き出されたことが分かります。
ちなみに `mode` は `production` `development` `none` の3種類を指定することができ、 `process.env.NODE_ENV` を設定してくれたり、本番用のプラグインを有効化したりしてくれるみたいです。

## エントリーポイントを変更する
Webpackはデフォルトで src/index.js をエントリーポイントとしてバンドルを開始しますが、人によっては `app.js` とか `main.ts` とかに変更したい場合もあると思います。
そういった場合、設定ファイルを下記のように変更します。

```javascript:config/webpack-dev.config.js
module.exports = {
  mode: 'development',
  entry: './src/main.js', // 追加
};
```

`src/index.js` を `src/main.js` に変更してコマンドを実行すると、無事にコンパイルされたことが分かります。

## 出力先を変更する
### ファイル名を変更する
バンドル結果のファイル名を `bundle.js` に変更したい場合は設定ファイルを下記のように変更します。

```javascript:config/webpack-dev.config.js
module.exports = {
  mode: 'development',
  entry: './src/main.js',
  output: {
    filename: 'bundle.js', // 追加
  },
};
```

### 出力先のディレクトリを変更する
ディレクトリの指定は絶対パスでなければならないので、 `path` を用いて下記のように変更します。

```javascript:config/webpack-dev.config.js
const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/main.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, '../build'), // 追加
  },
};
```

この状態でコマンドを実行すると、無事に `build/bundle.js` にバンドル結果が吐き出されます。

### 複数のエントリーポイントから複数のバンドル結果を出力する
`entry` はオブジェクト形式で複数のエントリーポイントを指定することができ、 `output.filename` は `[name].js` と指定することで元のファイル名をそのまま引き継ぐことができます。
これを利用して、設定ファイルを下記のように書くと複数のエントリーポイントからファイルをバンドルし、それぞれのバンドル結果を各エントリーポイントのファイル名で出力することができます。

```javascript:config/webpack-dev.config.js
const path = require('path');

module.exports = {
  mode: 'development',
  entry: {
    app: './src/app.js',
    main: './src/main.js',
  },
  output: {
    filename: '[name].js',
    path: path.resolve(__dirname, '../build'),
  },
};
```

設定変更に応じて必要なファイルを配置します。

```javascript:src/app.js
console.log('Hello from app.js');
```

```javascript:src/main.js
console.log('Hello from main.js');
```

```html:index.html
<!DOCTYPE html>
<html>
<head>
  <title>Webpack Level Up</title>
</head>
<body>
  <script type="text/javascript" src="./main.js"></script>
  <script type="text/javascript" src="./app.js"></script>
</body>
</html>
```

この状態で `webpack` コマンドを実行すると、 `build/app.js` および `build/main.js` の2種類のファイルが出力されていることが分かります。
また `webpack-dev-server` コマンドを実行すると、 `index.html` から2つのファイルを読み込むことができます。

ちなみに `[hash].js` のように指定するとdigest値に置換されます。使い方は [webpackでdigestをつけてキャッシュ対応 + digestされたファイルの参照](https://qiita.com/sugamondo/items/d70bd790db25c1037e92) を参考にすると良いと思います。

## まとめ
- entry でエントリーポイントのファイル名や位置を指定できる
- output でバンドル結果のファイル名や出力先ディレクトリを指定できる
- 複数エントリーポイントから複数ファイルを出力することができる

次回はWebpackに必須の loader の組み込み方法について調べていきます！

## 参考
今回利用したソースコードは [こちら](https://github.com/midwhite/webpack-level-up/tree/level-2) です。