webpack.config.jsがわからない

## webpack.config.jsがいつまでたってもわからない

Javascript開発には欠かせないwebpackですが、`webpack.config.js`ファイルの書き方がいつまで経っても検索&コピペばかりで身に付きません。別にコピペでいいじゃんという考え方もありますが、[webpackのドキュメント](https://webpack.js.org/concepts/)に沿って設定内容を理解し、自分の環境に合わせた形で`webpack.config.js`が書けるようにまとめていきたいと思います。バージョンは3.8.1の想定です。ディレクトリ構成も考えながらやっていきたいと思います。今のところ`project`ディレクトリ以下に次のようにファイルが存在しているとします。

```
project
- /node_modules/
- package.json
- webpack.config.js
```


```webpack.config.js
const path = require('path')

module.exports = {
    
}
```

ここからスタートです。


##  Concepts

`webpack.config.js`には大量の設定項目がありますが、まずは4つの中心的な項目について理解する必要があります。

- Entry
- Output
- Loaders
- Plugins


### Entry

webpackがビルドを始める際の開始点となるjsファイルで、エントリーポイントと呼びます。webpackはエントリーポイントに入ったあと、エントリーポイントがどのモジュールやライブラリに依存しているのかを判断し、処理してbundleと呼ばれるファイルに出力します。

```webpack.config.js
const path = require('path')

module.exports = {
    entry: path.resolve(__dirname, "entry.js"),
}
```

### Output

bundleファイルをwebpackがどこにどのような名前で出力すればいいのかを指定できます。`dist`ディレクトリの中に`bundle.js`という名前で出力するとしたら次のようになります。

```
project
- /node_modules/
- /dist/
- package.json
- webpack.config.js
```


```webpack.config.js
const path = require('path')

module.exports = {
    entry: path.resolve(__dirname, "entry.js"),
    output: {
    	path: path.resolve(__dirname, 'dist'),
    	filename: 'bundle.js'
    }
}
```

### Loaders

webpack自身はJavaScriptしか理解できませんが、Loaderを使うことによってJavaScript以外のものも処理できるようになります。どのような種類のファイルであってもwebpackが処理できるモジュールにLoaderが変換してくれることで、webpackがbundleファイルを作れるようになります。(モジュール化がwebpackの根本的な仕組みです)
Loaderには以下のような2つの目的があります。

- `test`プロパティに拡張子を指定して、あるLoaderがどのような種類のファイルを処理するべきなのか特定する(正規表現で拡張子を指定)
- `use`プロパティにLoaderを指定して、`test`プロパティに指定したファイルがアプリケーションの依存関係や最終的なbundleファイルに加えられるように変換する

```webpack.config.js
const path = require('path')

module.exports = {
    entry: path.resolve(__dirname, "entry.js"),
    output: {
    	path: path.resolve(__dirname, 'dist'),
    	filename: 'bundle.js'
    },
    module: {
    	rules: [
    		{ test: /\.txt$/, use: 'raw-loader' }
    	]
    }
}
```

この場合の指定だと、webpackに対してこう言っているのと同じです。

> "Hey webpack compiler, when you come across a path that resolves to a '.txt' file inside of a require()/import statement, use the raw-loader to transform it before you add it to the bundle."
>
> webpackさん、require()文の中で'.txt'で終わるようなパスに出会ったら、bundleファイルに追加する前にraw-loaderで変換してください。

### Plugins

Loaderがある種のモジュールを変換するのに対して、Pluginはwebpackができることの幅を広げてくれます。Pluginがあるとbundleファイルの最適化や環境変数の設定などいろいろなことができるようになります。Pluginを使うには、`require()`をして、`plugins`配列に追加する必要があります。configファイルの中で同じPluginを別の用途に使うことができるので、`new`演算子でその都度インスタンスを生成する必要があります。
[Plugin一覧](https://webpack.js.org/plugins)

```webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')

module.exports = {
    entry: path.resolve(__dirname, "entry.js"),
    output: {
    	path: path.resolve(__dirname, 'dist'),
    	filename: 'bundle.js'
    },
    module: {
    	rules: [
    		{ test: /\.txt$/, use: 'raw-loader' }
    	]
    },
    plugins: [
	    new webpack.optimize.UglifyJsPlugin(),
	    new HtmlWebpackPlugin({template: './src/index.html'})
  	]
}
```

## ここまでの感想

- Loaderの役割
- `module`プロパティは「こういう拡張子のファイルはこのLoaderでいい感じにTransformして」という指定だった
- Pluginはとりあえず使わなそう
- Loadersをもうちょっと掘り下げたい(Babelやscssで明らかによく見る)

次回はLoaderを掘り下げます。