BackboneやBootstrapなどの共通して使用するライブラリを、Webpackでbundleして一つにまとめる

# 前置き
Qiita初投稿です。GWだしとりあえず何か書いてみようと思い書いてみました。
記述方法、内容に関しておかしい点が多々あると思いますが、ビシバシ指摘していただけるとこちらとしても非常にありがたいです。


# 問題
BackboneやBootstrapを使用してWebアプリのフロントエンド部分を書いていたのですが、ViewやModelの数の増加と、それに伴った各モジュールの依存関係や読み込み順などの問題を解決するために、Webpackを導入しました。
Webpackを導入してこれらの問題が解決したのはいいのですが、各モジュール内で、

```js
var jQuery = require('jquery');
var $ = require('jquery');
var _ = require('underscore');
var Backbone = require('backbone');
```

などといちいち記述するのはめんどくさすぎるという問題がありました。

# 問題解決の方針
そのため、BackboneやBootstrapなどの共通して使用するライブラリは、`「vendor.bundle.js」`みたいなファイルにまとめて、htmlファイルで

```html
<script type="text/javascript" src="dist/vendor.bundle.js"></script>
<script type="text/javascript" src="dist/app.bundle.js"></script>
```

みたいな感じで、ライブラリをまとめた`vendor.bundle.js`ファイルと、そのページで使用するメイン処理をまとめた`app.bundle.js`ファイルを読み込んでやればいいのかなと思い、やってみました。
その記録です。

# 共通ライブラリをまとめる
## 設定ファイル
とりあえずwebpack.config.jsの全体を。

```js
var webpack = require('webpack');

module.exports = {
  entry: {
    vendor: [
      'jquery',
      'underscore',
      'backbone',
      'bootstrap',
      'bootstrap/dist/css/bootstrap.css'
    ],
    app: './src/script/app.js'
  },
  output: {
    path: __dirname + '/dist',
    filename: '[name].bundle.js'
  },
  module: {
    loaders: [
      { test: /\.html$/, loader: 'html-loader' },
      { test: /\.css$/, loader: 'style-loader!css-loader'},
      { test: /\.svg$/, loader: 'url-loader?mimetype=image/svg+xml' },
      { test: /\.woff$/, loader: 'url-loader?mimetype=application/font-woff' },
      { test: /\.woff2$/, loader: 'url-loader?mimetype=application/font-woff' },
      { test: /\.eot$/, loader: 'url-loader?mimetype=application/font-woff' },
      { test: /\.ttf$/, loader: 'url-loader?mimetype=application/font-woff' },
      { test: /\.png$/, loader: 'url-loader?mimetype=image/png' }
    ]
  },
  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      filename: 'vendor.bundle.js',
      minChunks: Infinity
    }),
    new webpack.ProvidePlugin({
      jQuery: 'jquery',
      $: 'jquery',
      _: 'underscore',
      Backbone: 'backbone'
    }),
    new webpack.optimize.UglifyJsPlugin({
      compress: {warnings: false},
      output: {comments: false},
      sourceMap: true
    })
  ],
  devtool: 'source-map'
};
```

上からざっくり見ていきます。

## entry
問題解決の方針に記述したように、共通ライブラリをまとめたものを読み込ませてから、メイン処理を行うjsファイルを読み込ませるため、上記のように設定します。
`vendor`配列の中に共通で使用するライブラリを記述していきます。
`app`は、BackboneのViewなどの分割した各モジュールを読み込んで処理を開始する地点。まぁごく一般的なエントリポイントです。

## output
今回はdist/に各bundleファイルを出力するため、pathを上記のようにしています。
`filename`では、`[name]`に`entry`で指定したキーが格納されるため、上記のように記述することで、共通ライブラリをまとめた`vendor.bundle.js`と、ページのメインの処理をまとめた`app.bundle.js`の2つがdist/に生成されます。

## module
使用するloaderに関して記述しています。
`html-loader`はunderscore.jsのテンプレート機能で記述したテンプレートファイルをモジュールとして読み込むために使用しています。
`style-loader`や`css-loader`、`url-loader`はBootstrapやcssファイル内の画像のために使用しています。

##plugins
### CommonsChunkPlugin
今回一番の重要な設定なのではないかと思います。
まず、`CommonsChunkPlugin`についてですが、公式のドキュメントによると、
**複数のエントリポイント間で共通して使用されるファイルを別ファイルとして作成する機能。(今回の例で言うと、app.bundle.jsのような)bundleファイルから共通モジュールを分離することで、作成されたチャンクファイルをはじめに一度ロードし、後で使用できるようにキャッシュに格納することができる。こうすることで、新しいページに遷移するたびにサイズの大きなbundleファイルをロードすることなく素早く配信できる。**
的な感じです（訳しただけですけど間違っていたらすみません）。
`CommonsChunkPlugin`についてはこちらの記事が参考になると思います。
[webpackのCommonsChunkPluginの使い方、使い所](http://qiita.com/soarflat/items/f8212434c4c3cb8ee00d)
今回はBackboneやBootstrapをまとめた、`vendor.bundle.js`を共通ファイルとして使うので、そのための設定になります。
#### 補足事項
以下の補足事項は記憶が曖昧なので無視した方がいいかもしれません。
最初、`CommonChunkPlugin`の設定を

```js
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.bundle.js')
```

のように記述したところエラーが出ました。
エラーの表示内容は忘れてしまったのですが、確かWebpackのバージョンの関係で新しいバージョンではこの記述方法では記述できない的なエラーだったと思います。なので

```js
new webpack.optimize.CommonsChunkPlugin({
    name: 'vendor',
    filename: 'vendor.bundle.js',
    minChunks: Infinity
})
```

みたいな書き方じゃないとダメなのかなーと。。。
一応公式のドキュメントを読んで上記のように記述したところうまくいきました。
補足終わり。

### ProvidePlugin
指定した変数を、その他のモジュールでも使えるようにする設定です。

### UglifyJsPlugin
jsファイルを`minimize`するとか、`SourceMap`を生成するかとかの設定です。

# 所感
以上、ホントにざっくりとした説明でした。
今回の例では、1つのページに対して`app.bundle.js`のように1つのbundleファイルを生成していますが、複数のエントリポイントがあり、その全てで`vendor.bundle.js`のような共通ファイルを使用する場合、更なる威力を発揮するのではないでしょうか。

# 終わりに
今更感はありますが、最近Reactを使ってチャットアプリとかチョロっとしたものを作ってみたのですが、Reactの威力に感動したので、そのことについても今後何か書けたらなーと考えています。