ベーシックなWebpackの導入と設定


毎回記事を見たりドキュメントを見ながら設定しているので、一度まとめてみる。
ドキュメントをもとにwebpackの設定と導入を行う。

## webpackのインストール
まずは、webpackのインストールを行う。


```bash
# 作業ディレクトリで行うものとする
yarn init
yarn add webpack --dev
```

## ディレクトリとファイルの準備
webpackはjsファイルの依存関係を解決するバンドラーである。
つまり、importされたモジュールやライブラリの依存関係を解決して１つのjsファイルを作成してくれる。
そのために、jsを自分で記述するファイルと自分が記述したファイルをまとめて吐き出すファイルが必要になる。
これらディレクトリから分けた方が管理がしやすいため、`src`と`dist`というディレクトリを作成する。
src/には自分で記述するjsファイルを、dist/にはsrc/に記述したjsファイルをまとめたものを吐き出すファイルを用意する。
ディレクトリ構成は以下のようになる。

```bash
project（作業ディレクトリ）
 |
 |-dist
 |  |-build.js
 |
 |-src
 |  |-index.js
```

Web上で使用されるのはバンドルされたbuild.jsになる。
build.jsを読み込むhtmlはdist/以下に置く。

結論としては以下のようになる。

```bash
project（作業ディレクトリ）
 |-package.json
 |-dist
 |  |-build.js
 |  |-index.html
 |
 |-src
 |  |-index.js
```

ディレクトリが準備できたらindex.jsに記述したり、必要に応じてsrc/以下にファイルを追加してそこに記述していったりする。
記述はES6や、より新しいEcmaScriptで書くと良さそう。
書き方は本記事では紹介しませんが、ライブラリや別ファイルで作成したクラスなどをimportすることで、必要以上にindex.jsが太ることもなく記述できます。

## webpackの実行
コードを記述したらバンドルして、build.jsに吐き出す。
以下のコマンドでwebpackを実行する。

```bash
./node_modules/.bin/webpack src/index.js dist/bundle.js
```

## webpackの設定をする
設定をすることで、コマンドにおいて吐き出し先のファイルなどを設定する必要がなくなる。
ディレクトリ直下に`webpack.config.js`を作成する。

```bash
project（作業ディレクトリ）
 |-package.json
 |-webpack.config.js
 |-dist
 |  |-build.js
 |  |-index.html
 |
 |-src
 |  |-index.js
```

webpack.config.jsには以下のように記述する。

```js
const path = require('path');

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

## スクリプトを書く
確認の度に、webpackを実行するのは面倒なので、`package.json`に実行コマンドを記述する。

```json
{
  ...
  "scripts": {
    "build": "webpack"
  },
  ...
}
```

変更の度に実行してほしい場合は、以下のようにする。


```json
{
  ...
  "scripts": {
    "build": "webpack --watch"
  },
  ...
}
```

あとは、CLIで以下のコマンドを実行する。

```bash
yarn run build
```

## webpack-dev-serverを導入する
yarn run buildで保存の度にwebpackが実行されるようになったが、ブラウザで確認するためには、毎回リロードしなくてはならない。
webpackが実行されたら、ブラウザにも反映されるようにしたいので、`webpack-dev-server`を導入する。

ターミナルで以下を実行する。

```bash
yarn add webpack-dev-server --dev
```

コマンドを短縮するために、package.jsonのscriptsに追加する。

```json
// 省略
"scripts": {
  "start: "webpack-dev-server --open"
}
```

これで、ターミナルで`yarn run start`とするとwebpackが実行され、そのあとでブラウザが立ち上がる。

## source mapを使用する
バンドルされたファイルでエラーが発見されたときに、バンドルされたファイルでエラー箇所が示されるが、実際に修正するべきなのは個々のファイルなので役に立たない。
バンドル前のファイルでエラー箇所を教えてもらうためにsource mapを使用する。
使用するには、webpack.config.jsに書き足すだけ。

```js
devtool: 'inline-source-map'
```

## Babelでトランスパイルする
webpackはバンドラーなので、ファイル内の依存関係を解決したファイルを生成するツール。
ブラウザが対応していないJavaScriptを記述すると動かなくなってしまう。
このようなJavaScriptをブラウザが対応しているJavaScriptに変換することをトランスパイルという。
トランスパイルを行ってくれるツールが`Babel`である。

### モジュールをインストールする
まずは、Babelなど必要なモジュールをインストールする。

```bash
yarn add babel-core babel-loader babel-preset-env --dev
```

webpack.config.jsにbabelを使用するように記述する。
`rules`の`loader`で`babel-loader`を指定する。

```js
module: {
  rules: [
    {
      test: /\.js$/,
      use: [
        {
          loader: 'babel-loader'
        }
      ]
    }
  ]
}
```

`.babelrc`というファイルを作成する。

```bash
project（作業ディレクトリ）
 |-.babelrc
 |-package.json
 |-webpack.config.js
 |-dist
 |  |-build.js
 |  |-index.html
 |
 |-src
 |  |-index.js
```

`presets`の設定でECMAScriptのバージョンをトランスパイルする。
`env`と指定したので、ECMASCript2017をECMAScript5に変換できる。

```json
{
  "presets": [
    [
      "env",
      {
        "modules": false
      }
    ]
  ]
}
```


## Reactを導入する場合
普段Reactを使っているので、Reactの導入を行いたい場合は、`babel-preset-react, react, react-dom`を追加する。

```bash
yarn add babel-preset-react --dev
yarn add react react-dom
```

webpack.config.jsに設定を追加する。
node_modulesをBabelのトランスパイル対象から外す。
reactやreact-domをトランスパイルするのを避けるため。

```js
const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  devtool: 'inline-source-map',
  devServer: {
    contentBase: './dist'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader',
          }
        ],
        exclude: /node_modules/,
      }
    ]
  }
};
```

.babelrcのpresetsにreactを追加する。

```json
{
  "presets": [
    "react",
    [
      "env",
      {
        "modules": false
      }
    ]
  ]
}
```

## 最後に
以上で最低限、webpack + babelでの設定はできるかと思う。
あとは、モジュールの追加や設定を必要に応じて行ったら良さそう。

## 参考
[webpack公式](https://webpack.js.org/)
[Babel公式](http://babeljs.io/)
[最新版で学ぶwebpack 3入門 – BabelでES2017環境の構築](https://ics.media/entry/16028)