LoginSignup
15
10

More than 5 years have passed since last update.

JSの最適化ツール「Prepack」を使ってみる

Posted at

Prepackとは

  • Facebookから公開されたJSをAOTコンパイルするツール
  • コードの最適化を行う
    • どんな変換がされるかは、こちらの例のようになる
  • コンパイル時に計算できるものは計算しておくので、ランタイム時の動作が早くなる
  • まだ出たばっかりで初期の開発段階
  • こちらのロードマップを見る限り、Prepack単体でES6が動く状態になるのは、まだ先(中期以降)
    • つまりBabelなどのトランスパイラで変換したコードに対して、Prepackを実行するようにしないと変換できない

たまたま見つけたprepack-webpack-pluginっていうのを使って、どんな感じになるか見てみたいと思います
https://github.com/TheLarkInn/prepack-webpack-plugin

ググるとeslint-plugin-prepackrollup-plugin-prepack的なのも開発中?なんですね

設定

yarn add prepack-webpack-plugin --dev
webpack.config.js
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つになります)

sample.js
(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

変換後 ↓

bundle.js
(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のアロー関数に変更 ↓

sample.js
(() => {
  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

変換後 ↓

bundle.js
(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有り ↓

 2017-05-09 17.57.18.png

11085ms

Prepack無し
 2017-05-09 17.59.13.png

396ms

だいぶ遅い
けど、ファイルサイズを見てもかなり最適化されたのは分かる

そのうち速度は改善されるかもしれませんが、Prepackの目指す所はそこでは無いと思うので、
今後、速度に問題が残れば、自マシンで開発時にはPrepackを使わずに、
本番やステージングにてPrepackを適用するというやり方になるかもしれません

感想

webpackなどの他のツールと併用して使うやり方になるか、Prepack単体でいけちゃうのか、
今後どうなるか分からないが、すごく強力なツールになるかもしれないので、追って見ていこうと思う

15
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
10