メモ。
webpack 2 正式リリース(バージョンは 2.2)だとか Tree Shaking という機能がいいらしい とかは目にしていたけど
結局 v1 -> v2 とメジャーバージョンが上がって Tree Shaking 以外に何が変わったの?というのがよくわからなかったので調べてみた。
なお、Tree Shaking については最後に記載している。
参考にしたサイト
「webpack 2 whats new」とかでググって、見つけられたのはここ。
What's new in webpack 2 · GitHub
(WIP て書いていて最新の情報かどうかわからないけど)ここに書いてある内容で気になったものをピックアップする。
なお、Getting Started with webpack 2 という記事は残念ながら v1 → v2 における新機能などについては言及されていなかった。
v2 からできるようになったこと
ES6 Modules をサポート
Babel を使ってトランスパイルしなくても import
, export
をそのまま解釈できるようになった。
ただし、Babel なしだと import/export
以外の ES2015 をトランスパイルしてくれるわけではない ので注意。
(こちらで確認した限り、たとえば const
は const
のまま、という意味)
また、Babel なしだと webpack.config.babel.js
というファイル名で ES2015 形式で書けるようにはならないので注意。
System.Import
による動的インポート
(2017/02/08追記)
Twitter で
System.importはdeprecatedになってimport()が使えるようになったというのが正解? https://t.co/MJ6JVMWWb5 "webpack2でTree Shaking以外に何ができるようにな…" https://t.co/Tf4k3VRbRL
— azu (@azu_re) 2017年2月8日
というのを教えていただいた。
確認したところ
Release v2.1.0-beta.28 · webpack/webpack
でたしかに
add
import()
as Code Splitting construct. It should be used instead ofSystem.import
when possible.System.import
will be deprecated in webpack 2 release (removed in webpack 3) as it's behavior is incorrect according to the spec.
という記載があったので、System.import()
のかわりに単に import()
を使った方がいい。
試していないが、以下 System.import()
部分を import()
に置き換えても動くはず。
(追記ここまで)
コード中に System.import('モジュールへのパス')
と書くことで動的にモジュールをインポートできる。
reuqire
と役目は同じ。
function onClick() { System.import("./module").then(module => { module.default; }).catch(err => { console.log("Chunk loading failed"); }); }
特徴としては System.Import
の結果が Promise として返される ところ。
これによりモジュール読み込みに失敗したときにこちら側でハンドリングすることができる。
System.Import
で読み込もうとしているモジュールはチャンクファイルとして本体のファイルとは別のファイルが生成されるよう。
たとえば上のコードを index.js
として、ディレクトリ構成が
├── src │ ├── index.js │ └── module.js └── webpack.config.js
webpack.config.js
が
module.exports = { entry: './src/index.js', output: { filename: 'bundle.js', path: path.resolve(__dirname, 'build') }, ...
となっていた場合、ビルド後は
├── build │ ├── 0.bundle.js │ └── bundle.js
となった。
また、
System.import("./routes/" + path + "/route")
のように変数で指定することも可能。
この場合は(require
のときも同じだと思うが)webpack は可能性のあるファイルを自動的に判別してくれる。
このときも可能性のあるモジュールファイルごとにチャンクファイルが生成される。
webpack.config.js で関数を export することが可能に
v1 のときは、webpack.config.js は
module.exports = { entry: './src/index.js', ... }
というようにオブジェクトを export していたが、関数を export することもできるようになった。
module.exports = function(options) { return { entry: './src/index.js', ... }; }
これで何が嬉しいのかと言うと、コマンドライン実行時に --env
を指定することでこの関数に任意の設定情報を渡せるようになった。
--env foo
のように文字列を渡すか、
--env.foo 1 --env.bar 2
のようにするとオブジェクトを渡すことができる。
例:
// webpack.config.js module.exports = function(options) { console.log(options); return { entry: './src/index.js', ...
# "scripts": { "webpack": "webpack" } は package.json に記載済み $ npm run webpack -- --env foo > webpack2-playground@1.0.0 webpack /Users/yamazaki/workspace/webpack2-playground > webpack "--env" "foo" foo $ npm run webpack -- --env.foo 1 --env.bar 2 > webpack2-playground@1.0.0 webpack /Users/yamazaki/workspace/webpack2-playground > webpack "--env.foo" "1" "--env.bar" "2" { foo: 1, bar: 2 }
webpack.config.js の書き方が一部変更
これは機能ではないが一応。
Migrating from v1 to v2 に従ってマイグレーションが必要。
おまけ:Tree Shaking について
最後におそらく webpack2 の目玉機能である Tree Shaking について。
すごいざっくりとした理解だけど、「export してるけどどこからも import されていないモジュールをバンドル時に自動的に削除して、ファイルサイズを小さくしてくれる」機能のよう。
Tree Shaking を利用するには Babel で import/export をトランスパイルしないように設定してあげる必要があり、具体的には .babelrc
で
{ "presets": ["es2015"] }
としていたところを
{ "presets": [["es2015", { "modules": false }]] }
のように変更してあげる必要がある。
ただ、
webpack2のTree Shakingの恩恵を受けるにはBabel側でCommonJS形式に変換しないよう["es2015", {"modules": false}]とする必要があるが、これをやるとgulpfile.babel.jsが動かなくなる
— Shingo Yamazaki (@zaki___yama) 2017年2月4日
で詰んでる
という問題にぶち当たった。これは、es2015 の preset を webpack.config.js に寄せるしかないのか...
日本語の解説記事だと冒頭でもリンク貼ったけどこちらが参考になる。
また、英語だと
Webpack 2 Tree Shaking Configuration – Modus Create: Front End Development – Medium
はわかりやすいが若干情報が古く、ただ サンプルコード の方は情報がアップデートされてるので参考にできる。
あとは
Tree-shaking ES6 Modules in webpack 2
だろうか。
おわりに
参考にしたサイト自体の情報が古かったり間違ってたりする可能性はあるが、とりあえず↑に書いたことは自分でも動作確認できた(webpack のバージョンは 2.2.1)。
日頃からリポジトリをウォッチしてたり changelog 見てたら正しい情報をキャッチアップし続けられるんだろうけど、そういうことできる人はほんとすごいなと思う。
(私はこういうことが知りたいと思ったときにどこを見るようにすればいいのかもよくわかってません...)