webpackのメモ

忘れないようにメモ。

## webpackとは
開発時のモジュールの依存関係を解決し、それらからコンテンツ提供時に必要となるアセット(js、css、image etc.)を最適化して生成してくれるツールです。

## webpackを使って今やってること

 * cssをjsとは別途エントリポイントとして管理、別ファイルに出力
 * jsのlintにeslintを使い、通知、logをターミナルに出力
 * cssのlintにstylelintを使い、通知、logをターミナルに出力
 * `webpack.optimize.CommonsChunkPlugin`を使い、react等のライブラリやmodule等、複数entryを作成する際に共通部分を把握して、ページ間でブラウザにキャッシュさせたい共有バンドルを抽出。

## webpackを使っているのにやってないこと

 * cssをjs内で扱う。(CSS Module)
 * 画像をjs内で扱う。
 * `webpack-dev-server`でautoReload等出来るdevサーバー立ち上げ。browserSync採用で見送り。

## webpackの基本的な使い方
### インストール
```sh
$ npm i webpack -d
```

-gオプションでglobalインストールしていれば、webpackコマンドがどこでも叩けるようになります。
ローカルインストールならnpm scriptにwebpackコマンドを登録してnpm run xxxで実行。
もしくは./node_modules/.bin/webpackを直接叩いても実行できます。

### 実行
```sh
$ webpack <entry> <output>
```
```sh
$ webpack ./src/main.js ./dist/app.js
```
上記の形でwebpackは実行されます。
entryにはエントリポイント、outputには出力ファイルを指定しますが、
これらはconfigファイルで指定するので、実際には指定していません。
下記は一部ですが、実行時にオプションを指定できます。

 `-d`
 webpackの開発モードオプション。
 内部で`--debug``--devtool``source-map``--output-pathinfo`が実行されています。
 `-p`
 webpackの本番用モードオプション。
 内部で`--optimize-minimize``--optimize-occurence-order`が実行されています。
 `--color`
 webpackのlogを色付きで出力。
 `--progress`
 標準エラー出力にコンパイルの進行状況を表示。
 `--watch`
 ビルド対象を監視し、依存関係にあるファイルも含め変化が発生すると再びビルド。
 `--config example.config.js`
 webpackコマンド実行時に利用するconfigファイルを指定。

## webpackのconfig
ワンライナーでエントリポイント等を管理するのは辛いので、一般的にはconfigファイルにビルドに必要な設定を記述します。

### configファイルの設置
`webpack.config.js`
というファイル名でnodeのワーキングディレクトリ直下に配置すると、webpackコマンド実行時に勝手に見にいってくれます。

```sh
project
├ node_modules/
├ dist/
├ src/
├ package.json
└ webpack.config.js ← ココ
```

`webpack.config.babel.js`
とすると、.babelrc経由でbabelなコードとして読んでくれます。(要babel)

ファイル名に縛られたくない場合や、rootに置きたくないなどの場合にはwebpackコマンド実行時に

```sh
$ webpack --config ./hogehoge.babel.js …
```
のようにwebpack実行時のconfigファイルを--configオプションで指定することができ、
開発向け、本番向けなどconfigファイルを分けて管理するというやり方もあります。

### configで使える便利なものたち

  `__dirname`
  現在実行中のソースコード(ここで言うwebpackのconfigが記述されているjs)が格納されているディレクトリの絶対パスが格納されている。
  `process.cwd()`
  nodeコマンド実行時のワーキングディレクトリの絶対パスを取得できる。
  `process.env.npm_lifecycle_event`
  webpackコマンドを実行したnpm script名が格納されている。

### configで指定してるもの
```js
const config = {
  context,
  entry,
  output,
  module: { loaders },
  plugins,
  ツール特有のものたち,
}
```
### configをwebpackに渡す

configオブジェクトをexportすることによってwebpackが認識出来るようになります。
また、arrayで複数渡す事が出来るので一度のwebpackコマンドで複数のタスクを扱うことが出来るようです。

```js
export default [config, config2]
module.exports = [config, config2]
```

#### context
webpackのconfig内のファイルパスの基準となるディレクトリを絶対パスで指定できます。
デフォルトは`process.cwd()`です。

```js
const context = __dirname
```

#### entry
エントリポイント(プログラム実行の起点になる場所)を指定します。
string、arrayまたはobjectでエントリポイントのパスを指定できます。
string、arrayならファイル名、objectならkeyで指定した名前を、
後述するoutput等で`'[name]'`として取得することができます。

```js
// 下記だとファイル名mainが[name]に
const entry = './src/js/main.js'
const entry = [
  './src/js/main.js'
]

// keyであるappが'[name]'に
const entry = {
  app :'./src/js/main.js'
}
```

#### output
生成したファイルをどこに格納するかを指定します。
  `path`
  生成されるファイルの格納ディレクトリ。
  `filename`
  生成されるファイル名。

```js
const output = {
  path: './dist/js',
  filename: '[name].js' // ← entryで指定したnameがココに
}
```

#### plugins

プラグインのインスタンスをarrayで指定していきます。
webpackに同梱されているものも幾つかあり適宜利用します。

```js
const plugins = [
  new webpack.DefinePlugin({
    'process.env': { 'NODE_ENV': '"production"' }
  }),
  new webpack.optimize.UglifyJsPlugin()
]
```

 * `extract-text-webpack-plugin`: css等を別ファイルに出力するためのもの。
 * `webpack-build-notifier`: 通知用プラグイン。
 * `webpack.DefinePlugin`: configからモジュールに対して設定値等の値を利用できるようにする。
 * `webpack.optimize.uglifyjsplugin`: mimify用のpulgin

※ process.env.NODE_ENVに'production'が設定されていない状態でUglifyJsPluginを使ってminifyすると、reactがエラーを吐いてしまうため、上記のようにwebpack.DefinePluginを使って設定した。もしくは実行時に`NODE_ENV=production`を添える。

#### module.loaders
webpackで外部ツールを利用するための各種loadersをobjectで定義し、arrayで指定していきます。

 * test: 対象ファイルを正規表現で設定します。
 * exclude: 除外ファイルを正規表現で設定します。
 * loader: loaderの文字列を指定します。

```js
const module = {
  loaders: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: 'babel',
    },
    {
      test: /\.js$/,
      exclude: /node_modules/,
      loader: "eslint-loader"
    }
  ]
}
```