Prepackとは
- Facebookから公開されたJSをAOTコンパイルするツール
- コードの最適化を行う
- どんな変換がされるかは、こちらの例のようになる
- コンパイル時に計算できるものは計算しておくので、ランタイム時の動作が早くなる
- まだ出たばっかりで初期の開発段階
- こちらのロードマップを見る限り、Prepack単体でES6が動く状態になるのは、まだ先(中期以降)
- つまりBabelなどのトランスパイラで変換したコードに対して、Prepackを実行するようにしないと変換できない
たまたま見つけたprepack-webpack-plugin
っていうのを使って、どんな感じになるか見てみたいと思います
https://github.com/TheLarkInn/prepack-webpack-plugin
ググるとeslint-plugin-prepack
やrollup-plugin-prepack
的なのも開発中?なんですね
設定
yarn add prepack-webpack-plugin --dev
const path = require('path')
const PrepackWebpackPlugin = require('prepack-webpack-plugin').default
module.exports = {
entry: [
path.join(__dirname, '../src/sample')
],
output: {
path: path.join(__dirname, '../dist'),
filename: 'bundle.js',
publicPath: '/'
},
plugins: [
new PrepackWebpackPlugin()
],
module: {
rules: [
{
test: /\.js$/,
use: 'babel-loader',
exclude: /node_modules/
},
]
}
}
実行
こちらの公式サイトの例から取ってきたコードで実行
(公式サイトには5つ例があるが、2つはPrepackのInitializationErrorで動かなかったので、それ以外のコード3つになります)
(function () {
function hello() { return 'hello'; }
function world() { return 'world'; }
global.s = hello() + ' ' + world();
})();
(function () {
function fibonacci(x) {
return x <= 1 ? x : fibonacci(x - 1) + fibonacci(x - 2);
}
global.x = fibonacci(23);
})();
(function(){
function fib(x) { return x <= 1 ? x : fib(x - 1) + fib(x - 2); }
let x = Date.now();
if (x === 0) x = fib(10);
global.result = x;
})();
webpackでビルド
webpack
変換後 ↓
(function () {
s = "hello world";
x = 28657;
var _$0 = Date.now();
if (typeof _$0 !== "number") {
throw new Error("Prepack model invariant violation: " + _$0);
}
result = _$0 === 0 ? 55 : _$0;
})();
sは文字列が連結された状態になってる
xは計算された状態になってる
resultもかなり最適化されてる
てかfunctionも1個になってるな
ES6のコード
これが1番どうなるか、見たかったのですが
ES6で書かれたコードをwebpackのbabel-loaderでトランスパイルして、それをPrepackできるか試してみます
ES6のアロー関数に変更 ↓
(() => {
function hello() { return 'hello'; }
function world() { return 'world'; }
global.s = hello() + ' ' + world();
})();
(() => {
function fibonacci(x) {
return x <= 1 ? x : fibonacci(x - 1) + fibonacci(x - 2);
}
global.x = fibonacci(23);
})();
(() => {
function fib(x) { return x <= 1 ? x : fib(x - 1) + fib(x - 2); }
let x = Date.now();
if (x === 0) x = fib(10);
global.result = x;
})();
webpackでビルド(webpack.configは上記のと同じ)
webpack
変換後 ↓
(function () {
s = "hello world";
x = 28657;
var _$0 = Date.now();
if (typeof _$0 !== "number") {
throw new Error("Prepack model invariant violation: " + _$0);
}
result = _$0 === 0 ? 55 : _$0;
})();
ちゃんと変換されたー
速度に関して
いつものwebpackに加えて、Prepackをするので
当然ビルド速度は落ちるのですが、どのくらい違うのか見てみました
使用するコードは、上のsample.js
Prepack有り ↓
11085ms
396ms
だいぶ遅い
けど、ファイルサイズを見てもかなり最適化されたのは分かる
そのうち速度は改善されるかもしれませんが、Prepackの目指す所はそこでは無いと思うので、
今後、速度に問題が残れば、自マシンで開発時にはPrepackを使わずに、
本番やステージングにてPrepackを適用するというやり方になるかもしれません
感想
webpackなどの他のツールと併用して使うやり方になるか、Prepack単体でいけちゃうのか、
今後どうなるか分からないが、すごく強力なツールになるかもしれないので、追って見ていこうと思う