英語資料を読むのが面倒な人のためのwebpack 2移行ガイド

2017年1月に、ようやくwebpack 2のリリースからbeta/rcが外れ、正式にリリースとなりました。
これによってnpm installでデフォルトに入るバージョンが2系となり、誰でも気軽に強力な追加機能のメリットを享受できるようになった一方、メジャーバージョンアップによる破壊的変更が加えられたことによって、従来のwebpack.config.jsは動作しない形となりました。

今回はまだまだ日本語の移行資料が少ないwebpack 2について、新しい機能と、1.xからの移行の方法を簡単にご紹介いたします。

## webpack 2の機能

webpackも2系になっていくつかの機能が追加されました。小さなものから、比較的大きなものまで様々ですが、今回は影響の大きそうなものをいくつかご紹介いたします。

### import/exportの標準対応

webpack 2では、import/export構文にbabel無しで対応できる変更が加えられるようになりました。
これまではwebpackはあくまでもモジュールバンドラーとしての役割にとどまる形となっており、ESの機能のトランスパイルなどには対応しておらず、必ずbabel及びbabel-loaderが必要になっていましたが、今回の変更によって、ES Moduleについてはこれが不要となりました。

```js:file_a.js
import "./file_b" // これで動く
file_b("hoge")
```

```js:file_b.js
export default function(word){console.log(word)}
```

### Tree Shaking

今ご紹介したimport/export構文のサポートですが、その理由はこのTree Shakingという機能の導入にあります。

Tree Shakingとは、ざっくりいうと「不要なコードを梳いてくれる機能」です。
webpackを用いてビルドする際、もし依存モジュールの中で、「どこからも依存がないexport」が存在した場合、それを削除してくれる機能となります。

不要なexportを削除するため、必然的に影響範囲はES Modulesを採用しているプロジェクトの範囲内となりますが、最近はCommonJSではなくこちらを採用しているプロジェクトも多いため、役に立つ人は多いのではないでしょうか。

Uglifyなどで最終的な圧縮や最適化はできるものの、webpack自体が持つことで、手軽に、かつ開発中の速度向上にも貢献するため、利便性の向上に大きく役立つことが予想されます。

![Screen Shot 2017-02-21 at 1.32.48.png](https://qiita-image-store.s3.amazonaws.com/0/75633/bc462da9-92b4-9756-eca6-b67fe37e468d.png)

### 動的Importの対応

これもwebpack 2の大きなポイントの１つであると私は考えていますが、動的にモジュールをimportすることが可能となりました。
これまではwebpack都合で一つ一つ丹精込めて手書きするしかなかったファイルを動的に読めるようになったため、コーディングが比較的になりました。

これによって、以下のような記法すら可能となります。

```js
const services = []
const serviceList = ["serviceA", "serviceB", "serviceD"];
serviceList.map((s)=>{
  System.import("./services/" + s)
  .then((mod)=>{
    services.push(mod);
  })
});
```

### -pオプション

-pをコマンドライン引数として渡すことで、NODE_ENVをproductionにしてくれる設定が追加されました。
これまではわざわざwebpack.config.jsを複数用意し、envプラグインを利用して書き換えていましたが、同一設定でdevelopmentかproductionかを判断したいだけであれば、1ファイルで可能となりました。

### その他の変更について

その他の変更点については、以下に項目が掲載されています。
他はあまり大きなものではないですが、気になる方は確認しておきましょう。

[ROADMAP - webpack](https://webpack.github.io/docs/roadmap.html)

## 1.xから2.xへの移行

さて、ここからが本題、肝心のwebpack 1.xから2.xへの移行方法となります。
改善版の移行ガイドは、英語であれば[公式サイト](https://webpack.js.org/guides/migrating/)に掲載されていますが、幾分量が多いため、よく引っかかるポイントだけに焦点を絞って移行します。

### 前準備

よくひっかかる場所について、先に対処しておきます。

#### node_modulesを一旦削除しておく

入れながら全てが対応しているかを試していると、バージョン周りで混乱することがあるので、事前に一度削除しておきましょう。

```
$ rm -Rf ./node_modules/
```

#### 依存モジュールの更新

ここがはじめの鬼門で、まずは自分が依存しているloader周りが全て2.xに対応しているかを確認します。
例としてVue.jsの場合、オフィシャルの[vue-loader](https://github.com/vuejs/vue-loader)は対応済みなのでスムーズに移行できますが、[vue-ts-loader](https://github.com/HerringtonDarkholme/vue-ts-loader)でTypeScriptを利用していた場合、まだ非対応なので諦めざるを得ません。

基本的なloaderは大体対応しており、対応状況はangular-cliやvue-cliといった、公式のスキャッフォルディングツールの更新状況を追うと大体は把握できますが、移行中に非対応がわかるとコストが大きいので、事前に調べておきましょう。

この確認ができ次第、全てを更新した後に、webpack.config.jsを書き換えていきましょう。

### webpack.config.jsの更新

#### loader記法の更新

移行時に必ずしなければならないのが、このloader記法の置き換えです。
単純な置換ですが、loaders項目はrules項目に切り替わり、「loaderを指定する」というよりは、「使うローダーを選ぶrulesを記述する」という概念となりました。

以下のBefore/Afterの形に合わせ、以下を書き換えてください。

```js:webpack.config.before.js
module.exports ={
  module: {
    loaders: [
      {
        test: /\.js$/,
        loader: 'babel'
      }
    ]
  }
}
```

```js:webpack.config.after.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: "babel-loader"
      }
    ]
  }
}
```

#### json-loaderの削除

webpack 2からはデフォルトでJSONに対応することとなったため、json-loaderは不要となりました。
もしプロジェクトで利用している場合は、削除しておきます。

```js:webpack.config.before.js
module.exports ={
  module: {
    loaders: [
     {
       test: /\.json/,
       loader: "json-loader"
     }
    ]
  }
}
```

```js:webpack.config.after.js
module.exports = {
  module: {
    rules: [
      {
      }
    ]
  }
}
```

#### -loaderの付与

最後に想定されるハマりどころは-loaderについてです。

webpack 2からは、loader名を指定する時の-loaderの省略記法がサポートされなくなりました。
もし利用している場合は、省略しない形にしましょう。

```js:webpack.config.before.js
module.exports ={
  module: {
    loaders: [
     {
       test: /\.css/,
       use: "css"
     }
    ]
  }
}
```

```js:webpack.config.after.js
module.exports = {
  module: {
    rules: [
      {
        test: /\.css/,
        use: "css-loader"
      }
    ]
  }
}
```

#### その他の移行について

基本的にはloader周り以外はあまりトラブルが起きにくい移行ですが、他の問題が発生した場合は以下の公式ドキュメントより確認が可能となっております。

[Migration from v1 to v2](https://webpack.js.org/guides/migrating/)

## おわりに

webpack 1 to webpack 2は、一見loaderの仕様変更によりハードルが高く見えがちですが、実際はトラブルが起こりやすいのはほぼそこだけであるため、自身の利用しているフレームワークが対応している場合は、できるだけ2系にあげるのがスムーズです。

既に公式としては1.xはdeprecatedとなっており、これからは2.xが中心となって開発されてゆくので、機能が膨れ上がらない今のうちに移行しておくことをオススメします。

特に、大きなプロジェクトであるほど、Tree Shakingによるファイルサイズ削減の恩恵は受けやすいかと思いますので、是非移行してみましょう。