Tree shaking (ツリーシェイキング)は、ウェブ開発のひとつで、使っていないコードを削除する事で、JavaScriptを軽くするものです。ここでは、 tree shakingをwebpackと同じように使いこなせるよう説明しています。
Tree Shakingとは何か?
Tree shakingは、ライブコードとして知られていますが、ECMAScriptでつくられた、コードを最適化するための方法です。アプリを長く使っていると、いくつか使われない機能が出てきます。その使われない機能が多くなると、アプリの動きが悪くなります。tree shakingは、使っていないJavaScriptを削除して、必要なものだけにするのが目的です。もし、あなたのアプリに不必要なものが溜まっていると思うなら、これできれいになります。
使っていないコードを探すのは、スクリプト作成言語では難しいことでした。しかし、ECMAScript 6モジュールが開発されたことによって可能になりました。このコンセプトは、2015年にRollupで開発されていますが、現在多くの開発者は tree shakingを使っています。webpackは、version 2からES6とtree shakingを提供していますが、webpack 4では、いくつかの機能が追加されています。
なぜTree Shakingは動くのか?
JavaScriptは、imagesやHTMLより処理能力がかなり高いです。なぜなら、実行前に解析して処理するからです。ウェブ開発者がJavaScriptコードをまとめる前に整しなければならないのは、こういう理由があります。たとえば、下の画像は、170KBのJavaScriptと170KBのJPEGの実行時間を対比しています。
全体的に、tree shakingは、コードを分けるよりも、JavaScriptを分類して、操作を高速化させるのに効果的です。2つを組み合わせることによって、動作が速くなったが、そのほとんどが、余計なつながりを切ることで実現した。
Tree Shaking はどのように動くか?
Tree shakingは、 JavaScriptの中で必要なモジュールだけを取り出します。開発者が構築している時、モジュールは自動的に組み込まれます。しかし、生産性を高めるためには、webpack の中から必要なモジュールを取り入れる必要があります。そうすることで、JavaScriptが少ない容量で早く動くようになります。
import arrayMenu from "array-menu";
このコードは、array-menuという、webpackでモジュールからすべてインポートするときに使います。しかし、あなたの作ったアプリはwebpackの一部しか使いません。なので、すべてユーザーに送る必要はありません。あなたのアプリがモジュールのすべてが必要でなければ、必要なものだけ指定することができます。
import { burger, fries, shake } from "array-menu";
残念ながら、 tree shaking は、現在自動化されていません。なので、手動で作業しなければいけません。アプリのメインファイルを整理して、使っていないモジュールを確認してください。それから、必要なものを入れてください。
Tree Shakingを始める前に
もし JavaScriptを Babelのように使いたいなら、tree shakingをする前にいくつか準備が必要です。 babel-preset-envのように、モジュールをES6からCommonJSにしてください。この工程は、tree shakingでは複雑です。だから、事前にES6を削除しておかなければいけません。これができたら、Babelファイルに、下のコードを入れてください。
{
"presets": [
["env", {
"modules": false
}]
]
}
次に、作成者が、分析できるようにして、使っていないコードを選んでいかなければなりません。しかし、tree shakingを使うためには、 minificationを動かす必要があります。すると、UglifyJS Pluginが使えるようになります。
ここまでできたら、webpackで使っていないコードがわかり抽出されます。そして、UglifyJSで、抽出されたコードを削除します。
Tree Shaking のコード実例
webpackにある、Tree Shaking の例を見てみましょう。Tree Shaking がどのように動くかわかるはずです。( Alex Bachuk作成)
modules.js
ファイルを次のように定義してください。
export function drive(props) {
return props.gas
}
export function fly(props) {
return props.miles
}
次に、index.js
ファイルを次のようにしてください。
import { drive } from modules;
eventHandler = (event) => {
event.preventDefault()
drive({ gas: event.target.value })
}
この例では、fly() は重要ではありません。なので、入れなくてもいいです。 tree shakingがUglifyJSを使って、不要なコードを抽出して削除してくれます。
webpackでは、必要なものと不要なものを、「harmony export (immutable)」 と「unused harmony export」に分けてくれます。 UglifyJSでこれらを区別するために、optimization.usedExportsが動くようにしておく必要があります。最小の工程では、unusedに入っているコードは、削除されません。Rollupを使えば、削除することができます。この例では、Tree shakingは、少しのコードしか削除していません。しかし、プロジェクトが大きい時は、細かく分けて抽出することができます。
追記
- もしtree shakingが作動していないと思ったら、ES6がCommonJSより優先されていないか確認してください。webpack-common-shakeのようなプラグインは、CommonJS モジュールをサポートしていると聞いていますが、念のためES6モジュールは切っておいたほうがいいです。
- Lodashでtree shakingを入れたときは、Babelに babel-plugin-lodash を追加してください。
- 指定した範囲外の所を修正するのは、tree shakingでは複雑になってしまいます。eslint-plugin-tree-shaking のようなプラグインを使えば、簡単になります。
- 多くのモジュールの中から不要なものを探し出すのは難しいです。 webpack-bundle-analyzer を使うと簡単になります。
- tree shaking がうまく起動しなくてもがっかりしないでください。tree shakingはJavaScriptにしか対応しません。このメソッドを他のコードとつなげると動くようになります。
Tree shaking (ツリーシェイキング)のまとめ
もちろん、違うアプリを使えば違う結果になります。ですが、tree shakingは入れる価値があります。アプリの容量が小さくなるように、JavaScriptを構築するのに効果的です。開発者にとってもユーザーにとっても、JavaScriptを整理するのに有効です。