traceur-compilerでスクリプトをあらかじめコンパイルしておく方法
traceur-compilerを使って書いたプログラムを公開しようというとき、ユーザー側でコンパイラのプログラムのロードとスクリプトのコンパイルが走ってしまうのが速度の点で気になります。そこであらかじめコンパイルしておく方法を紹介します。
スクリプトをコンパイルする方法
Windowsな人も別にビルドなどする必要なくいけます。
Node.jsのインストールとリポジトリのclone
まず、Node.jsをインストールします。
次にtraceur-compilerのリポジトリをcloneします。 https://github.com/google/traceur-compiler
>node traceur
を実行してみる。すると「npm install commander」を実行しろといわれるので言われた通りにする。そして再びnode traceurを実行すると
Error: At least one input file is needed Usage: traceur [options] [files] Options: -h, --help output usage information --out <FILE> Compile all input files into a single file --sourcemap Generate source maps --longhelp Show all known options --experimental Turns on all experimental features Examples: $ traceur a.js $ traceur b.js c.js --out compiled.js
というように出力されます。
traceurという名前でコマンドが使えるようにする
"node
Windowsの場合はPATHの通った場所に以下の内容でtraceur.cmdというファイルを作ります。
@node C:\Users\User\repos\traceur-compiler\traceur %*
C:\Users\User\repos\traceur-compilerの部分はあなたがcloneした場所に変更します。
UNIXの人はPATHの通った場所にcloneしたワーキングディレクトリの中にあるtraceurというファイルへのシンボリックリンクを置くだけでいいです。
実際に簡単なスクリプトをコンパイルしてみる
こんなファイルを用意します (t.js)
class Hello { hello(x) { console.log(`Hello, ${x}.`); } } new Hello().hello("world");
次のコマンドでコンパイルします。
traceur --out compiled.js t.js
するとcompiled.jsがこんな内容で生成されます。
var $__getDescriptors = function(object) { var descriptors = {}, name, names = Object.getOwnPropertyNames(object); for (var i = 0; i < names.length; i++) { var name = names[i]; descriptors[name] = Object.getOwnPropertyDescriptor(object, name); } return descriptors; }, $__createClassNoExtends = function(object, staticObject) { var ctor = object.constructor; Object.defineProperty(object, 'constructor', {enumerable: false}); ctor.prototype = object; Object.defineProperties(ctor, $__getDescriptors(staticObject)); return ctor; }; var Hello = function() { 'use strict'; var $Hello = ($__createClassNoExtends)({ constructor: function() {}, hello: function(x) { console.log(("Hello, " + x + ".")); } }, {}); return $Hello; }(); new Hello().hello("world");
コンパイル済みのファイルをブラウザで実行してみる
こんなファイルを用意して開きます。
<!DOCTYPE html> <title>hello</title> <script src="https://raw.github.com/google/traceur-compiler/master/bin/traceur.js"></script> <script src="compiled.js"></script>
bin/traceur.jsはデカすぎてロードに時間がかかるので小さくしたい
bin/traceur.jsにはコンパイラ部分も含まれているので巨大です。必要なのはランタイム部分だけなので、それだけをロードしたいものです。
ランタイム部分のソースはsrc/runtime/runtime.jsにまとめられています。これはJS.nextではなくJSで書かれているので、これだけロードすればいいんではないかと考えたくなります。
しかし、traceur.runtime.elementGetなどの実装がruntime.jsの外で定義されているtraceur.optionsというものに依存しております。
function elementGet(object, name) { if (traceur.options.trapMemberLookup && hasPrivateNameProperty(object, elementGetName)) { return getProperty(object, elementGetName).call(object, name); } return getProperty(object, name); }
traceur.options.trapMemberLookupの真偽を見ているだけなので"traceur.options={trapMemberLookup:false}"とかどこかに入れてしまうといい方法もありますがちょっと美しくないです。
そこでコンパイラ部分を除いたバイナリを作ってしまいましょう。
traceur-compilerのワーキングディレクトリ内の/srcにtraceur-mini.jsというファイルを以下の内容で作ります。
module traceur { import {options} from './options.js'; export options; export var runtime; export function setRuntime(rt) { runtime = rt; } }
そして/srcがカレントディレクトリである状態で以下を実行します。
>node ../traceur --out traceur-mini.compiled.js traceur-mini.js runtime/runtime.js
するとtraceur-mini.compiled.jsができます。今まで使っていたbin/traceur.jsの代わりにこれを使いましょう。
最後に、作ったtraceur-mini.compiled.jsとbin/traceur.jsのサイズを比べてみます。
C:\Users\User\repos\traceur-compiler>ls -lh bin\traceur.js src\traceur-mini.compiled.js -rw-rw-rw- 1 User 0 808K 2013-04-13 12:02 bin\traceur.js -rw-rw-rw- 1 User 0 19K 2013-04-13 12:44 src\traceur-mini.compiled.js
Linuxだとカレントディレクトリがリポジトリのルートの状態で以下を実行してうまくいったのですが、Windowsだとパス名の扱いに問題があるようでうまくいきません。
上では本当は/bin/traceur-mini.jsに出力したかったのですが、出力先ディレクトリが異なるとこれまた失敗するので現在のディレクトリにtraceur-mini.compiled.jsという名前で出力するようにしておきました。>node traceur --out bin/traceur-mini.js src/traceur-mini.js src/runtime/runtime.js