React.jsをwebpackを使ってbuildしてみた

## はじめに
React.jsで実装したアプリケーションをbuildする手段は様々ありますが、今回はwebpackを使ってbuildする場合についてまとめてみました。

## 対象
これからwebpackでbuild処理を書こうとしている方、なんとなくwebpackを知りたい方

## Webpackって何??
webpackはbuild用のツールで、複数にまたがるファイルの依存関係を解消し結合したり分割することができるツールです。
他にも同様の機能をなすツールとして、gulpやgruntなどがありますが、これらはタスクを定義するツールであり、build処理をメインで行うために作られたツールではありません。（もちろん、build処理を書くことはできますが。）

## fmfm...でも、ちょっとよくわからない..
今まで、htmlファイルでJSを使いたい場合、普通は以下のような形で読み込んでいたはずです。

```index.html
<html>
  <head>
    <script src="//code.jquery.com/jquery-1.11.2.min.js"></script>
    <script src="./assets/hogehoge.js"></script>
    <script src="./assets/fugafuga.js"></script>
  </head>
</html>
```

現状は3つのファイルですが、もしこれが10, 20...100となった場合どうでしょう??
リクエストの回数が増えて、アプリケーションのパフォーマンスも下がりますよね??
しかし、webpackを使えば、上記の問題が解決でき、下記のようにすっきりとまとまります。

でも、この量ならファイルを圧縮するタスクを書けば事足りることなのでは??
もちろん、それでも可能です。
しかし、その際、gulpなどで圧縮し1つにまとめるタスクを書いた場合、読み込むファイルの順番やパスなどを意識する必要があります。
webpackの良いところは、そういった気にせず自動でやってくれるメリットがあります。

```index.html
<html>
  <head>
    <script src="./assets/bundle.js"></script>
  </head>
</html>
```

これで、1つのファイルをhtmlが読み込めば良いだけなので、パフォーマンスは以前のものより上がります。
このように、複数にまたがったファイルを結合したり、分割してくれるBuildに特化したツールがwebpackなのです。

## セットアップ
まずは、package.jsonを作成するために、下記のコマンドを実行します。
package.jsonとは、そのアプリケーションで使用したいパッケージのバージョンや依存関係などを管理してくれるツールです。
RailsではGemfileというファイルが同様の役割をになっていました。
Railsで、必要なパッケージはgemというもので提供されており、Gemfileにそれらを定義し、`bundle install`することで、アプリケーション内で使用することができていました。
これと同様に、webpackはnpmのパッケージですので、まずは、packageを管理するための管理場所を作成する必要があります。
それがpackage.jsonと呼ばれるファイルで、下記のコマンドを打つことで生成されます。

```javascript
$ npm init
```

## npmとは??
npmは、Node Package Managerの略称のことで、
Node.jsで作られたパッケージ管理ツールのことです。
Railsの実装の際には、bundlerなどがありましたね。

## インストール
次に、webpackをインストールします。
Railsでいうところの `bundle install`と同じです。
Railsでは、bundlerでgemを管理していたため、`bundle install`というコマンドでしたが、
今回は、npmでpackageを管理するため、`npm install`というコマンドを使用します。

```javascript
$ npm install webpack --save-dev
```

## `--save`, `--save-dev` の違い
package.jsonに記述する方法として、Railsでbundle installlにオプションが複数あったように、npmでも同様に存在します。
大きく2つ存在しており、それぞれの違いは下記の通りです。(他にも存在するが、詳しく知りたい方は公式documentを確認してください。)

### `--save`とは
- package.jsonの `dependencies`に記述される
- package.jsonを外部の人がinstallする際、全てinstallされる
- 主にpackageやアプリケーションをの実行に必要なものは、`dependencies`で管理する。

### `--save-dev`とは
- package.jsonの `devDependencies `に記述される
- 開発する際に必要なpackageの管理のために使う。

## 試しに、webpackを使ってみよう！

```sub.js
var introduction = "はじめまして。koyabuです";
module.exports = introduction;
```

```app.js
var introduction = require('./sub.js')
console.log(introduction)
```

このように2つのファイルを作成してみます。
そして、webpackコマンドを使って、これらを1つのファイルとして結合し出力します。

```
$ webpack app.js bundle.js
```

この時何をやっているのかというと、app.jsというエントリーポイントのファイルをwebpackが読み込み、依存関係を解消した後、1つにまとめたものをbundle.jsに出力しています。

ここで疑問点が生じますよね。エントリーポイント??出力??
これらに関して、次に説明します。

## エントリーポイント(entry)とは
エントリーポイントとは、そのアプリケーションにおいて1番最初に呼び出されるファイルのことを指します。通常、HTMLファイルがこの役割を担います。HTMLファイルが読み込まれた後、同ファイルに読み込むよう定義してあるJSファイル読み込まれ、実行されます。

## 出力先(output)とは
エントリーポイントのファイルを通じて、様々なファイルの依存関係を解決しつつ結合したり分割した結果を出力する先です。
例えば、以下のように2つのファイルが分かれて存在する場合、webpackはこれらを1つにまとめ、出力し、結果としてブラウザに「Hello world」を表示することを可能にします。

```Main.js
import React from 'react';
import Sub from './Sub';

export default class Main extends React.Component {
  return <Sub >;
}
```

```Sub.js
import React from 'react';

export default class Sub extends React.Component {
  return (
    <div>Hello world</div>
  );
}
```

```javascript
$ webpack Main.js dist/client.js
```


## webpack.config.jsの作成
なんとなく、webpackの使い方はわかってきた。
でも、本来アプリケーションって、そんな2,3のファイルしかないものではないし、もっと複雑なものである。
自分好みのbuildの設定をしたい。そんな要望が出てくるのではないでしょうか??
そんなときは、webpack.config.jsを作成します。
webpack.config.jsとは、build時の設定ファイルにあたり、このファイルに記述した通りにbuild処理を編集することができまます。

```
$ touch webpack.config.js
```

```webpack.config.js
module.exports = {
  entry: './src/client.js',
  output: {
    path: __dirname + '/public',
    fiename: 'client.js',
  },
};

```

## Buildしてみる
こうして記述したwebpackを実際に起動させるには2つの方法があります。

1つ目は、globalにwebpackをinstallし、webpack-dev-serverコマンドでbuildをする。

```javascript
$ npm install -g webpack-dev-server
$ webpac-dev-server
```

2つ目は、package.jsonのscriptsにタスクを定義し、起動

```package.json
"scripts": {
  "start": "webpack-dev-server"
},
```

scriptに定義した後、下記のコマンドでbuildをかけます。

```
$ npm run start
```

この際、webpackの設定により、デフォルトでは、 `http://localhost:8080`、または `http://localhost:8080/webpack-dev-server/`からアクセスすることが可能になります。

## JS以外のファイルはどうやってBuildするの??
一般的にJSファイルだけで1つのアプリケーションが作られることは珍しいのではないでしょうか??
普通は、JSファイル以外にcssファイルなど拡張子の異なるファイルも生成されます。
そういったファイルをwebpackでは、module.loadersを使ってbuildすることが可能です。

## Loaderとは??
Loaderとは、Babel、画像データ（jpeg,png,etc）、cssファイル(css, sass, stylus, scss, etc)など様々なファイルを読みこめる、webpackの拡張機能です。

## Loaderは、どうやって使うの??
loaderを使うには、npmで提供されているloaderのpackageをinstallして、それらを使い、対応するファイルをインストールしたloaderを通してbuildするようにwebpackに書くことで使用することが可能です。

## fmfm...つまり...??
例えば、cssをwebpackを使いbuildしたい場合、下記のように記述します。
まずは、使用するloaderのinstall。
以下のものは開発上必要なものなので、`--save-dev`を使ってinstallします。
```
$ npm install style-loader css-loader --save-dev
```

ここで色々初めて見るものが登場していますね。
test?? loader??

```webpack.config.js
module.exports = {
  // 本来はentry, outputなどが定義されているが、今回は省略
  module: {
    loaders: [
      {
        test: /\.css$/,
        loader: 'style-loader!css-loader',
      },
    ],
  }
}
```


## module.loadersでやっていること
必要なloaderは、module.loadersを使って定義します。

### test
- ビルド対象（loaderを使ってbuildしたいもの）を指定できます。
- 正規表現を使って指定することができます。
- 今回の例だと、拡張子が`css`であるものを正規表現を使い、testに定義しています。

### loader, loaders
- 使用するloaderを定義します。
- 複数のloaderを使う場合は、`!`を使い複数記述します。
- 今回の例だと、style-loaderとcss-loaderを使っています。
- loadersは配列で定義することが可能です。`例: loaders: [style-loader!css-loader]`
- 左から右の順でloaderは読み込まれる。
- `--loader`の部分は省略することが可能

# まとめ
webpackの大体の流れは理解できたでしょうか??
今回は最低限必要な処理のみで一通りの流れを記述してみました。
今回ご紹介したもの以外に、様々な処理を書くことができるので、必要に応じて公式documentなどをご確認してみてください。