Node.jsとclosure-compiler(略してCC)を一緒に使用したプロジェクトはありますか?
CCの公式の推奨事項は、アプリケーションのすべてのコードをまとめてコンパイルすることですが、require("./MyLib.js")
を含む単純なnode.jsコードをコンパイルすると、その行は出力に直接配置されますが、作成されません。その文脈での任意の意味。
いくつかのオプションがあります。
まだリリースしていないプロジェクトでClosureCompilerをNodeで使用しています。少しのツールが必要ですが、多くのエラーをキャッチするのに役立ち、編集もかなり短いです-再起動-テストサイクル。
まず、Closureコンパイラ、ライブラリ、およびテンプレートを一緒に使用するために、 plovr (これは私が作成および保守したプロジェクトです)を使用します。 Nodeコードをクロージャーライブラリのスタイルで記述しているので、各ファイルは独自のクラスまたはユーティリティのコレクション(_goog.array
_など)を定義します。
次のステップは、使用したいNode関数のexternファイルの束を作成することです。これらのいくつかを次の場所で公開しました:
https://github.com/bolinfest/node-google-closure-latitude-experiment/tree/master/externs/node/v0.4.8
最終的には、文書化する機能がたくさんあるので、これはもっとコミュニティ主導のものになるはずだと思います。 (一部のNode関数には、最後の引数ではなくオプションの中間引数があり、型の注釈が複雑になるため、これも煩わしいです。)作業を行うことができる可能性があるため、この動きを自分で開始していません。クロージャーコンパイラーを使用して、これをより厄介なものにします(以下を参照)。
Node名前空間http
のexternsファイルを作成したとします。私のシステムでは、http
が必要なときはいつでもそれを含めることにしました。 :
_var http = require('http');
_
そのrequire()
呼び出しをコードに含めていませんが。代わりに、クロージャーコンパイラの_output-wrapper
_機能を使用して、ファイルの先頭にすべてのrequire()
を追加します。これは、plovrで宣言すると、現在のプロジェクトでは次のようになります。
_"output-wrapper": [
// Because the server code depends on goog.net.Cookies, which references the
// global variable "document" when instantiating goog.net.cookies, we must
// supply a dummy global object for document.
"var document = {};\n",
"var bee = require('beeline');\n",
"var crypto = require('crypto');\n",
"var fs = require('fs');\n",
"var http = require('http');\n",
"var https = require('https');\n",
"var mongodb = require('mongodb');\n",
"var nodePath = require('path');\n",
"var nodeUrl = require('url');\n",
"var querystring = require('querystring');\n",
"var SocketIo = require('socket.io');\n",
"%output%"
],
_
このように、私のライブラリコードはノードのrequire()
を呼び出すことはありませんが、コンパイラはそれらをexternとして認識するため、コードでのhttp
などの使用を許容します。それらは真の外部ではないので、私が説明したようにそれらを前に付ける必要があります。
最終的に、これについて話し合った後 ディスカッションリストで 、より良い解決策は、次のような名前空間の新しい型注釈を付けることだと思います。
_goog.scope(function() {
/** @type {~NodeHttpNamesapce} */
var http = require('http');
// Use http throughout.
});
_
このシナリオでは、externsファイルはNodeHttpNamespace
を定義し、ClosureCompilerがexternsファイルを使用してプロパティをタイプチェックできるようにします。ここでの違いは、http
の型はこの特別な名前空間型になるため、require()
の戻り値に任意の名前を付けることができることです。 (_$
_の「jQuery名前空間」を特定することも同様の問題です。)このアプローチにより、Node名前空間のローカル変数に一貫して名前を付ける必要がなくなり、 plovr構成のその巨大な_output-wrapper
_。
しかし、それは余談でした...上記のように設定すると、次のようなシェルスクリプトが作成されます。
RAW
モードでビルドします。node
を実行します。RAW
モードを使用すると、すべてのファイルが大きく連結されます(ただし、SoyテンプレートやCoffeeScriptをJavaScriptに変換することもできます)。確かに、行番号が意味をなさないため、これはデバッグを面倒にしますが、これまでのところ十分に機能しています。クロージャーコンパイラーによって実行されるすべてのチェックは、それだけの価値があります。
クロージャーコンパイラのsvn HEADは AMDのサポート
以前のアプローチをより単純なアプローチに置き換えました。
新しいアプローチ
面白いことに、require()
呼び出しにexternを追加する必要さえありませんでした。 Google Closureコンパイラは、それを自動的に理解します。私は 私が使用するnodejsモジュールのexternを追加する必要がありました。
古いアプローチ
OPの要求に応じて、Google ClosureCompilerを使用してnode.jsコードをコンパイルする方法について詳しく説明します。
私はbolinfestが問題を解決した方法に触発され、私の解決策は同じ原理を使用しています。違いは、モジュールのインライン化を含むすべてを実行する1つのnode.jsスクリプトを作成したことです(bolinfestのソリューションではGCCがそれを処理します)。これにより、自動化が進みますが、壊れやすくなります。
サーバーコードをコンパイルするために実行するすべてのステップにコードコメントを追加しました。このコミットを参照してください: https://github.com/blaise-io/xssnake/commit/da52219567b3941f13b8d94e36f743b0cbef44a
要約する:
require()
呼び出しを検出します。var Server = require('./lib/server.js');
require()
呼び出しが含まれるため、すべてのrequire()
呼び出しがなくなり、すべてのコードを含む1つの巨大な文字列が残るまで、ステップ3と4を再帰的に繰り返します。require
呼び出しをコンパイル済みコードにプリプリメントします。コンパイル済みのコード。
すべてのrequire
呼び出しが削除されます。私のコードはすべてフラット化されています。
http://Pastebin.com/eC2rVMiN
コンパイル後のコード。
Node.jsコアのrequire
呼び出しが手動で追加されました。
http://Pastebin.com/uB8CaejN
このようにすべきではない理由:
require
呼び出しを検出し、module.exports
をインライン化および削除するために、正規表現(パーサーまたはトークナイザーではない)を使用します。これは、すべての構文バリエーションを網羅しているわけではないため、脆弱です。なぜあなたがすべきか:
Node.jsのクロージャーライブラリを60秒で。
サポートされています。チェックしてください https://code.google.com/p/closure-library/wiki/NodeJS 。