dackdive's blog

新米webエンジニアによる技術ブログ。JavaScript(React), Salesforce, Python など

webpack.config.jsの読み方、書き方

(2017/08/28追記)

この記事は webpack v1 系での config について書かれています。
v2 系以降は一部の項目名などに変更があります。

Migrating from v1 to v2
を読んで v2 系への移行を行うか、または私のリポジトリを参考にしてください。

https://github.com/zaki-yama/react-redux-template
https://github.com/zaki-yama/redux-express-template

(追記ここまで)

はじめに

webpack を使った JS/CSS のビルドを行う場合、webpack.config.js という設定ファイルを用意してコマンド自体は webpack で済ませることがほとんどだと思いますが
公式チュートリアルでも webpack.config.js については少ししか触れられていなかったので、よく使う項目についてメモしておきます。
(項目の一覧は https://webpack.github.io/docs/configuration.html に記載されています)

また、ちょうどこの記事を書こうと思ったときに、英語ですが非常にわかりやすい記事が投稿されてました。

今回は取り上げなかった webpack-dev-server の設定についても言及されているし、とにかく説明が丁寧でわかりやすいです。オススメ。

(2016/05/07追記)
webpack-dev-server についても書きました。

(追記ここまで)

目次


webpack.config.js の例

React と ES2015 を使ったアプリ開発なんかでよく見る webpack.config.js は、たとえばこのような形です。

module.exports = {
  entry: __dirname + "/index.js",
  output: {
    path: __dirname + '/dist',
    filename: 'bundle.js'
  },

  module: {
    loaders: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        query:{
          presets: ['react', 'es2015']
        }
      }
    ]
  },
  devtool: 'source-map',
  resolve: {
    extensions: ['', '.js', '.jsx']
  }
};

各項目について、順番に見ていきます。


entry

ビルドの起点となるファイルのパスを指定します。
起点とは、要するにここからさまざまなファイルを require しているファイルのことです。

entry は文字列で単一のファイルを指定することも、Array または Object で複数のファイルを指定することもできます。
複数指定する場合、Object だと出力ファイルも複数になります(output の項で触れます)が、Array だと出力されるファイルは1つです。
ので、どういった目的で使うのかあんまりわかってません。


output

output.path に出力先のパスを、output.filename に出力ファイル名を指定するのが一般的です。

なお、entry に Object を渡して複数のエントリーポイントを指定した場合、出力も複数のファイルになりますが
その場合には output.path[id][name] などの特殊な変数を使用します。

module.exports = {
  entry: {
    module1: './entry.js',
    module2: './entry2.js'
  },
  output: {
    path: __dirname + '/dist',
    filename: '[name].bundle.js'  // entry の key (module1, module2) が渡される
  }
};
結果
$ ls dist
module1.bundle.js  module2.bundle.js


module.loaders

メインとなる部分です。
対象のファイルを変換するための loader を指定します。

modules.loaders は Array になっており、Array の要素は以下の項目を持った Object です。

  • test
  • includeexclude
  • loader または loaders
  • query
test

ビルド対象(Loader を適用するファイル)を指定します。正規表現が使えます。

include, exclude

ビルド対象に含める/除外するファイルを指定します。正規表現が使えます。

loader または loaders

適用する loader の名前を指定します。xxx-loader-loader 部分は省略可能です。

  • loader を使った場合、複数の loader の指定は ! 区切りで記述します
module: {
  loaders: [
    {
      test: /\.css$/,
      loader: 'style!css'
    }
  ]
}
  • loaders を使った場合、配列で loader を指定します
module: {
  loaders: [
    {
      test: /\.css$/,
      loaders: ['style', 'css']
    }
  ]
}

いずれの方法でも複数の loader が指定可能ですが、右から左に適用されることに注意しましょう。

また、loader は webpack とは別に npm でインストールする必要があります。
たとえば、例として紹介している babel-loader については、ドキュメントにもあるように

$ npm install babel-loader babel-core babel-preset-es2015 babel-preset-react --save-dev

とする必要があります。(この場合に関しては、presets も個別インストールが必要のようですね)

query

loader に渡したいクエリパラメータを指定します。

まとめると

冒頭の

loaders: [
  {
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    query:{
      presets: ['react', 'es2015']
    }
  }
]

は、node_modules ディレクトリ配下を除き、拡張子が .js のファイルすべてに対し、babel-loader という loader を適用します。
また、適用する際、loader に reactes2015 という preset を指定します。


devtool

デバッグのための SourceMap の出力を設定することができます。
SourceMap とはビルド前後の JS ファイルの対応関係情報を持ったファイルで、これを出力するとブラウザの開発者ツールなどでビルド前のコードを参照することができます。

f:id:dackdive:20160413103044p:plain

参考:
SourceMap について調べてみました。 | イントフロート スタッフブログ
Introduction to JavaScript Source Maps - HTML5 Rocks

webpack では、devtool に指定する値によって出力される SourceMap の形式およびビルド速度に差があるようです。一覧表をドキュメントから引用します。

devtool build speed rebuild speed production supported quality
eval +++ +++ no generated code
cheap-eval-source-map + ++ no transformed code (lines only)
cheap-source-map + o yes transformed code (lines only)
cheap-module-eval-source-map o ++ no original source (lines only)
cheap-module-source-map o - yes original source (lines only)
eval-source-map + no original source
source-map yes original source

それぞれの細かな違いについてきちんと理解できてませんが、開発時は inline-source-mapsource-map、本番ビルド時には eval を指定しているものが多い気がします。
eval だと元のコードを確認できるのかどうか、よくわからず。。。


resolve

こちらもいくつかパラメータがあるようなのですが、よく見るのは extensions です。
ビルド対象に含めたい(require している)ファイルの拡張子を Array で指定します。

デフォルトは

["", ".webpack.js", ".web.js", ".js"]

です。
たとえば React ファイルの拡張子を .jsx で作っていた場合、こちらに記述する必要があります。
※ただし、指定すると デフォルト値を上書き(デフォルト値に追加ではなく)してしまうので注意

foo.jsrequire('foo') というように拡張子なしで読み込みたい場合は '.js' を指定する必要があり、
逆にデフォルト値以外の拡張子のファイルを require('myfile.ext') というように拡張子つきで読み込みたい場合、'' (空文字列)を指定する必要があるとのこと。


おわりに

webpack.config.js でよく出てくる項目にいて整理しました。
これでたいていのアプリの設定ファイルは読めるんじゃないでしょうか。

今回紹介したもの以外だと webpack-dev-server がらみで plugins とか devtool とかありますが、それはまた別の記事で整理したいと思います。

(2017/03/07追記)

本番環境用のビルドについて書きました。

(追記ここまで)