twitter buttonfacebook buttongoogle plus buttonhatena bookmark buttonpocket button
ちょっと小さいのはたしかですが。
2017年2月5日

rollup-plugin-pursでPureScriptのモジュールを結合する(インライン化、デッドコード排除)

purescriptrollup.js


現状のPureScriptでは、コンパイル後のモジュールを結合するのに

  • browserifyやwebpackを使って通常のCommonjsモジュールとして結合する方法(でかい)
  • psc-bundleを使って結合する方法(デッドコード削除が効くので、こっちのほうが断然結合後のファイルサイズが小さい。ただしかなり遅いし、PureScriptから出力されたCommonjsモジュールしか結合できないので、それ以外のCommonJSモジュールを結合するにはさらにwebpackなどをキメる必要がある)

の2種類があります。ここで、新たにrollupのプラグインrollup-plugin-pursを使う方法が加わったようです。特徴としては、

  • psc-bundleと同様のデッドコード排除が効きます
  • さらにインライン化もある程度効くようで、結合後のファイルサイズのさらなる削減とともに、実行効率の向上も期待できます

となんだかとても良さげです。使い方はrollupをインストールして、

$ npm install -g rollup

rollup-plugin-pursをインストールして、

$ npm install --save-dev rollup-plugin-purs

なんかこんな感じにrollup.config.jsを書いて、

import purs from "rollup-plugin-purs";

export default {
  entry: "src/Main.purs",
  dest: "bundle.js",
  format: "iife",
  sourceMap: true,
  plugins: [
    purs()
  ]
};

rollupを実行するだけです。

$ rollup --config

たとえば、

sum x y = x + y

main = logShow (sum 20 22)

こんなかんじのコードをpsc-bundleで結合すると、

  var sum = function (dictSemiring) {
      return function (x) {
          return function (y) {
              return Data_Semiring.add(dictSemiring)(x)(y);
          };
      };
  };
  var main = Control_Monad_Eff_Console.logShow(Data_Show.showInt)(sum(Data_Semiring.semiringInt)(20)(22));

こんな感じのコードがそのまま結合されるのですが、rollup-plugin-pursで結合した場合は、

  var _main = _logShow_uncurried(_showInt, ((_semiringInt.add)(20)(22)));

だけが吐かれて、sumの呼び出しがインライン化されて消滅してるのが確認できました。また、_logShow_uncurriedという関数が見えますが、これは関数_logShowのカリー化を解除したバージョンで、次のような関数がrollup-plugin-pursによって自動的に定義されます。

  var _logShow_uncurried = function (_dictShow, _a) {
    return _log2((_dictShow.show)(_a));
  };

そして、引数がすべて与えられた場合はカリー化が解除されたバージョンが使われるようになるようです。PureScriptは関数がデフォルトでカリー化されるので関数呼び出しが多くなり効率上のオーバーヘッドが大きいのですが、これで少しはオーバーヘッドが低減できそうです。ただし、私が試した範囲ではエラーが出て結合できないモジュールもありました。なんかシングルクォーテーションがついた名前の関数がお気に召さないようです。まだ実用的な完成度とまでは言えませんが、メリットが多いので今後に期待したいところです。

まだ議論の最中のようですが、pscも将来的にはES6モジュールを吐くようになるかもしれません。また、ブラウザ環境などでもES6 modulesが使えるようになれば、psc-bundleのようなツールで結合する必要自体がなくなるかもしれません。つーかES6 Modulesはやくしろよ!今どきモジュールがない言語なんてアホくさくて使ってられんわ!

参考

  • https://github.com/Pauan/rollup-plugin-purs/issues/6 一部のコードでエラーが起こるのは、acornの既知の問題っぽいです。すでに修正されているので、rollupがバージョンアップされれば直るかも
  • https://github.com/purescript/purescript/issues/2574#issuecomment-277434874
  • https://github.com/Pauan/rollup-plugin-purs