Webpack はじめの一歩


**このページは作業ログです。やったことをつらつら書くだけなのでまとめません。あしからず。**

## モチベーション 
 
JavaScript界隈のビルドツールは雨後の筍のように色々あるね。GruntやらGulpやらはたまたmakeを使いましょうっていう記事もある。最近出てきたWebpackがReact界隈だとよく使われているので試してみる。

## チュートリアルをやってみる

- [Webpackのチュートリアル](http://webpack.github.io/docs/tutorials/getting-started/)はこちら
- [Qiitaに日本語でまとめられた方がいる。そちらを参照することをオススメする。](http://qiita.com/cortyuming/items/ba4c4d61fdf262bc2303)

1. まず最初は設定ファイル無しから始まる。entry.jsを用意しただけの所からbundle.jsをwebpackで作り、htmlに読ませる。
2. 次も設定ファイルなし。`require`文を使って他のファイルの内容を読み込んだentry.jsを作り、htmlの読み込ませる。
3. 引き続き設定ファイルなし。`npm install css-loader style-loader`を実行してローダーを追加。`node_modules`にあるローダーを追加するらしい。マジか。もう一個ビックリしたのがjsファイルにcssのロードを書くのか。マジか。
4. 設定ファイルなんかない。`require("!style!css!./style.css");`の`!style!css!`っていうのはローダーの指定だったんです。(ここまで解説ない)ローダーの指定はコマンド実行時にも指定できるよ、っていうのがここ
5. やっとこさ設定ファイル登場。webpackはカレントディレクトリにある`webpack.config.js`を自動で利用する。
6. 進捗を出したい時は`webpack --progress --colors`というように打つ。
7. ファイルの変更監視するwatchモードあり〼`webpack --progress --colors`
8. 開発用サーバーもあるでよ。`webpack-dev-server --progress --colors` Express/Socket.ioを使い、ファイル変更があったら表示しているブラウザを自動でリロードしてくれる。かしこい。

## 用語の整理

- Loader : 各種リソースファイルの変換方法を定義したもの。JavaScript以外のファイルも対象。node.jsで書ける。同期/非同期
- Plugin : UglifyJSのように別ツールを組み込んだり、何か処理を差し込むためのもの [プラグイン一覧](http://webpack.github.io/docs/list-of-plugins.html)

## なぜ webpack なのか？

[Pete Hunt(Instagram.com)氏のOSCON2014での講演がわかりやすい。](http://youtu.be/VkTCL6Nqm6Y)browserifyなどでは[不十分な理由](https://www.youtube.com/watch?v=VkTCL6Nqm6Y&feature=youtu.be&t=1537)の要点を訳すと、

- browserifyやrequirejsは依存関係を解釈して統合した1つの大きなJSを生成することができるが、分割してロードすることができない。
- gruntやgulpはCSSや画像などの依存関係を解釈することができない。
- WebpackはJSだけではなくCSSやHTML等の依存関係を解釈してファイルを統合できる。また、複数のファイルに分割し、ページ毎にスクリプトをロードできる。

## Configurationで気になるところ

### entry周り

```webpack.config.js
   entry: [
     'webpack-dev-server/client?http://localhost:3000',
     'webpack/hot/only-dev-server',
     './js/index.js'
   ],
```

entryに含まれる`webpack-dev-server/client?http://localhost:3000`とか`webpack/hot/only-dev-server`とかなんだろう？entryに含まれているので、webpackを実行するとこれら２つのURIからコンテンツを取得し、concatされる。concatしていいファイルかどうかが問題。それぞれざっくり推測すると

- `webpack-dev-server/client?http://localhost:3000`は名前から推測するに`Webpack Dev Server`の機能をconcatするために追加しているように見える。
- `webpack/hot/only-dev-server`はHot Reloadingをサポートするためのスクリプトに見える。

それぞれについて少し見てみる。

#### Webpack Dev Serverとは

[ドキュメントによると](http://webpack.github.io/docs/webpack-dev-server.html)Webpack Dev ServerはExpress製のサーバーで、[webpack-dev-middleware](http://webpack.github.io/docs/webpack-dev-middleware.html)を使ってwebpack後のコンテンツを配信する。`webpack-dev-middleware`はassetsをコンパイルしたものをメモリ上にキャッシュするなどを担当する。`webpack-dev-middleware`は２つのモード`watch mode`と`lazy mode`がある。`watch mode`はコンテンツが更新され次第assetのコンパイルを行い、`lazy mode`はentry pointにアクセスがあった時にassetのコンパイルを行う。`webpack-dev-middleware`は、assetのコンパイルが終わるまで、コンテンツの配信を遅らせる。


##### [脱線]APIサーバーをProxyする

フロントエンド開発時は、バックエンドサーバーと分離して開発することがあるが、そうすると大抵フロントエンドサーバーとバックエンドサーバーでポートが違うので、ブラウザのCross Origin Policyに引っかかってAPIサーバーにアクセスできない。

Webpack Dev Serverの場合もProxyできるので、特定のURIをバックエンドサーバーにプロキシを設定する。起動時のオプションに下記を追加すればよい。

```javascript
  proxy: {
    "/api/*": "http://localhost:8080" // /api以下にアクセスがあった場合はhttp://localhost:8080に流す
  }
```

##### [脱線]Webpackのログを色付けする

Webpackを使ったログを色付けするには同様に下記を追加すればよい。

```javascript
  stats: {colors: true}
```


```server.js
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');

new WebpackDevServer(webpack(config), {
  publicPath: config.output.publicPath,
  hot: true,
  historyApiFallback: true,
  stats: {colors: true}, // webpackのログを色付けする
  proxy: {
    "/api/*": "http://localhost:8080" // /api以下にアクセスがあった場合はhttp://localhost:8080に流す
  }
}).listen(3000, 'localhost', function (err, result) {
  if (err) {
    console.log(err);
  }

  console.log('Listening at localhost:3000');
});
```

#### Hot module replacement with webpack (webpackを使ったモジュールの動的置き換え)とは

[ドキュメントによると](http://webpack.github.io/docs/hot-module-replacement-with-webpack.html)ページ再読み込みをすることなく、アプリケーションの起動中にモジュールの追加、削除を行う機構のこと。ページ毎に動的にスクリプトを読み込めるようコードを塊毎に分割している場合は、変更があったモジュールに関連するスクリプトだけ読み込み直すように設計されている。ページ全体をリロードする必要がないので、高速化が期待できる。

Productionでも使えるけど、実験的機能という位置づけで、バグもあるだろう、という機能。

## 参考URL

- [webpack で始めるイマドキのフロントエンド開発](http://qiita.com/yosisa/items/61cfd3ede598e194813b)
- [Webpack Howto](https://github.com/petehunt/webpack-howto)