是否有任何项目一起使用node.js和closure-compiler(简称CC)?
官方的CC建议是一起编译应用程序的所有代码,但是当我编译一些包含require("./MyLib.js")
的简单node.js代码时,该行直接放入输出中,但它没有在这种背景下有任何意义。
我看到了几个选项:
答案 0 :(得分:50)
我一直在使用Closure Compiler with Node来完成尚未发布的项目。它已经采用了一些工具,但它有助于捕获许多错误并且具有非常短的编辑 - 重启 - 测试周期。
首先,我使用plovr(这是我创建和维护的项目),以便一起使用Closure编译器,库和模板。我以Closure Library的样式编写Node代码,因此每个文件都定义了自己的类或实用程序集合(如goog.array
)。
下一步是为要使用的Node函数创建一组externs文件。我在以下公开发表了其中一些内容:
https://github.com/bolinfest/node-google-closure-latitude-experiment/tree/master/externs/node/v0.4.8
虽然最终,我认为这应该是一个更加社区驱动的东西,因为有很多功能需要记录。 (这也很烦人,因为一些Node函数有可选的中间参数而不是最后一个参数,使得类型注释变得复杂。)我自己没有开始这个动作,因为我们可以用Closure Complier做一些工作来减少它的尴尬(见下文)。
假设您已为节点名称空间http
创建了外部文件。在我的系统中,我已经决定,只要我需要http
,我将通过以下方式包含它:
var http = require('http');
虽然我的代码中没有包含require()
调用。相反,我使用Closure Compiler的output-wrapper
功能,在文件开头添加所有require()
s,在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%"
],
通过这种方式,我的库代码从不调用Node的require()
,但是编译器在我的代码中容忍使用http
这样的东西,因为编译器将它们识别为externs。因为它们不是真正的外在因素,所以必须按照我的描述进行前提。
最后,在谈到这个on the discussion list之后,我认为更好的解决方案是为命名空间创建一个类型的新类型注释:
goog.scope(function() {
/** @type {~NodeHttpNamesapce} */
var http = require('http');
// Use http throughout.
});
在这种情况下,externs文件将定义NodeHttpNamespace
,以便Closure Compiler能够使用externs文件对其进行类型检查。这里的区别在于您可以将require()
的返回值命名为您想要的任何内容,因为http
的类型将是此特殊命名空间类型。 (为$
标识“jQuery命名空间”是一个类似的问题。)这种方法可以消除为一致地为Node命名空间命名局部变量的需要,并且不需要在那里使用那个巨型output-wrapper
。 plovr config。
但这是一个题外话......一旦我按照上面所述设置了东西,我就有了一个shell脚本:
RAW
模式构建所有内容。node
。使用RAW
模式会导致所有文件的大量连接(尽管它还负责将Soy模板甚至CoffeeScript转换为JavaScript)。不可否认,这使得调试变得很痛苦,因为行号是无稽之谈,但到目前为止我一直运作良好。 Closure Compiler执行的所有检查都使它值得。
答案 1 :(得分:6)
闭包编译器的svn HEAD似乎有support for AMD
答案 2 :(得分:3)
我用一种更简单的方法取代了我的旧方法:
新方法
有趣的是,我甚至不必为require()
电话添加外部电话。 Google Closure编译器自动理解这一点。我确实必须add externs for nodejs modules that I use.
旧方法
<击> 撞击>
<击>根据OP的要求,我将详细阐述使用Google Closure Compiler编译node.js代码的方法。
我受到了bolinfest解决问题的方式的启发,我的解决方案使用了同样的原则。不同之处在于我创建了一个执行所有操作的node.js脚本,包括内联模块(bolinfest的解决方案让GCC负责处理)。这使它更加自动化,但也更脆弱。
我刚刚为编译服务器代码的每一步添加了代码注释。请参阅此提交:https://github.com/blaise-io/xssnake/commit/da52219567b3941f13b8d94e36f743b0cbef44a3
总结:
require()
个调用,包括分配部分
在start.js中,这匹配一个需要调用:var Server = require('./lib/server.js');
require()
个调用,所以我会递归重复第3步和第4步,直到所有require()
调用都消失为止,我留下一个包含所有代码的大字符串。require
对已编译代码的调用。预编译代码。
所有require
来电都已删除。我的所有代码都被夷为平地
http://pastebin.com/eC2rVMiN
编译后的代码。
Node.js核心require
调用已手动添加
http://pastebin.com/uB8CaejN
为什么你不应该这样做:
require
个调用,内联和删除module.exports
。这很脆弱,因为它不包括所有语法变体。为什么你应该:
<击> 撞击>
答案 3 :(得分:2)
Node.js上的Closure Library在60秒内完成。
支持,请检查https://code.google.com/p/closure-library/wiki/NodeJS。
答案 4 :(得分:-22)
选项4:不要使用闭包编译器。
节点社区中的人不倾向于使用它。你不需要缩小node.js源代码,这很愚蠢。
根本没有用于缩小的好处。
关于关闭的性能优势,我个人怀疑它实际上会使你的程序更快。
当然还有成本,调试编译的JavaScript是一场噩梦