Browserifyユーザーがwebpackを覚え始めるには

JavaScriptのバンドラーには今のところBrowserifyを使っているけど、webpackもどんなものか把握したいという人のための記事です。

記事執筆時点（2017/11）では、webpackのバージョンは3.8.1です。

# とりあえずJavaScriptをバンドルする例

まずは単純な設定でwebpackを使ってみます。
必要なnpmパッケージはその名の通り`webpack`だけです。インストールしましょう。

```
npm install --save-dev webpack
```

基本的に、webpackの設定はwebpack.config.jsというJavaScriptファイルに書いていきます。
このファイルをpackage.jsonなどと同じディレクトリに作ります。
これが基本ですが、以下の様にもできます。

- （npm scriptsやgulpなどを通して）webpackを実行する際のオプションによって、明示的に設定ファイルを指定してもよい。
- ファイル名をwebpack.config.**babel**.jsにすれば、設定ファイルの中でES2015のimport/exportを使える。詳細は[こちら](https://webpack.js.org/configuration/configuration-languages/)。そうしなくてもconstなどは使えるらしく、公式サイトのサンプルでもwebpack.config.jsの中でconstを使っている（この記事でもそうします）。

とりあえずJavaScriptをバンドルする設定の例として、webpack.config.jsを以下の様に書きます。

```webpack.config.js
const path = require('path'); // Node.jsの組み込みのモジュール

// 各種設定を含んだオブジェクトをexportするのが基本の書き方。
module.exports = {
  entry: './src/js/index.js', // エントリーポイントとなるjs
  output: {
    filename: 'bundle.js', // バンドルされて出力されるjsのファイル名
    path: path.resolve(__dirname, 'dist')　// バンドルの出力先ディレクトリ
    // pathは絶対パスである必要があり、絶対パスを簡単に指定するためにpath.resolve()を使っている。
  }
};
```

そうしたら、npm scriptsから`webpack`コマンドを実行するなどして、webpackを実行します。
これで、Browserifyと同じ様にJavaScriptをバンドルできます。

# webpackを通してBabelを使う

次の一歩として、ES2015+で書かれたJavaScriptをトランスパイルするために、webpackを通してBabelを使う例を紹介します。
既にBabelを使っている人向けの説明ということで、Babel自体の説明は省略します。

まずは`babel-loader`というnpmをインストールします。

```
npm install --save-dev babel-loader
```

他にも、Babel自体を使うために`babel-core`や`babel-preset-env`なども必要ですが、今までBabelを使っていた人なら既にインストールしているだろうという想定で、省略します。

そして、以下の様に設定を追加すればOKです。これでトランスパイルできるようになります。

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

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  // ここから追加
  module: {
    rules: [
      {
        // src/jsディレクトリ以下のjsファイルに、"babel-loader"を適用する。
        test: /\.js$/,
        include: path.resolve(__dirname, 'src/js'),
        use: [ 'babel-loader' ]
        // Babelに関する設定をここに書き加えることもできるが、この例では.babelrcファイルに別途書いてあるものとする。
      }
    ]
  }
};
```

さらっとbabel-loaderというものが登場しました。
ローダーというのはwebpackの核となる概念の一つで、JavaScriptの中で何かをimportする際の前処理を行います。
babel-loaderは、Babelを使ったトランスパイルを行うローダーであり、上記の例ではそれをjsファイルに適用しているわけです。

# webpackを通してUglifyJSを使う

別の例として、バンドルしてできたbundle.jsを圧縮するために、webpackを通してUglifyJSを使う例を紹介します。

今度は`uglifyjs-webpack-plugin`というnpmをインストールします。
これのdependencyに`uglify-js`が含まれているようで、`uglifyjs-webpack-plugin`だけインストールすればOKです。

```
npm install --save-dev uglifyjs-webpack-plugin
```

そして、以下の様に設定を追加すればOKです。

```webpack.config.js
const path = require('path');
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')　
  },
  // ここから追加
  plugins: [
    new UglifyJSPlugin() // 色々とオプションの指定もできるが、今回の例では何も指定しない。
  ]
};
```

今度はuglifyjs-webpack-pluginというものが登場しました。
プラグインもwebpackの核となる概念の一つで、ローダーにはできないその他もろもろの処理を行わせることができます。
uglifyjs-webpack-pluginは、単純にJavaScriptにUglifyJSを適用するプラグインです。

# ここから先、どのようにwebpackを覚えていくか

以上がwebpackの基礎となります。まずentryとoutputを与えて、必要に応じてローダーやプラグインを取り入れていくことになります。

webpackのことをもっと知るには、まずは公式ドキュメントの[CONCEPTS](https://webpack.js.org/concepts/)に一通り目を通すのがおすすめです（CONCEPTS直下のConseptsのページだけでなく、Entry Points、Outputなどのページを一通り）。

設定の書き方を詳細に知るには、[CONFIGURATION](https://webpack.js.org/configuration/)を見ます。
結構な量の項目があり、知りたい時に知りたい部分を見るのが良いと思います。

[API](https://webpack.js.org/api/)には、一口に"API"とまとめるのもどうかというぐらい、色々な意味でのAPIが説明されています。

[GUIDES](https://webpack.js.org/guides/)では、上から順に読み進みながら、webpackの役立つ使い方を把握していくことができます。
CONCEPTSの次ぐらいに読むといいかも。自分に必要ないと思う部分はとりあえず読み飛ばしてもOK。

[LOADERS](https://webpack.js.org/loaders/)と[PLUGINS](https://webpack.js.org/plugins/)には、主なローダーとプラグインがずらっと並んでいます。
ざっと眺めて、自分に役立ちそうなものを探すといいでしょう。

# ここから先、どのようにwebpackを使っていくか

uglifyjs-webpack-pluginの例を見た時、「webpackの**中で**わざわざプラグイン経由でuglifyせずに、webpackの**後に**素のuglifyを呼べば良いのでは」と思った人もいるのではないでしょうか。それはそれで正しいと私は思います。

設定を追加していけば、webpackはあれもこれもできるようになります。そうしても良いですし、使い慣れた素のnpmパッケージが他にあるなら、webpackの前後でそれを呼ぶようにしても良いでしょう。

他にもwebpackを使えば、スタイルシートや画像さえもJavaScriptの中でimportできるようになったりもします。この域に来ると、バンドルする元となるソース自体にwebpack流の書き方が入ってきます。

どこまでwebpackを活用するかは、自分の状況に応じて自分で決めていくのが良いと思います。