有没有同时使用node.js和closure-compiler(简称CC)的项目?
官方的 CC 建议是一起编译应用程序的所有代码,但是当我编译一些包含 require("./MyLib.js")
的简单 node.js 代码时,该行直接放入输出中,但在该上下文中没有任何意义。
我看到几个选项:
- 将整个应用程序编码为一个文件。这通过避免它解决了问题,但不利于维护。
- 假设所有文件将在执行前连接起来。这再次避免了问题,但更难实现未编译的 Debug模式。
- 我想让 CC“理解”node.js 的 require() 函数,但如果不编辑编译器本身,这可能无法完成,对吗?
最佳答案
我一直在将 Closure Compiler 与 Node 一起用于我尚未发布的项目。它需要一些工具,但它有助于发现许多错误,并且编辑-重新启动-测试周期非常短。
首先,我使用 plovr (这是我创建和维护的项目)以便一起使用 Closure 编译器、库和模板。我以 Closure Library 的风格编写我的 Node 代码,因此每个文件都定义了自己的类或实用程序集合(如 goog.array
)。
下一步是为您要使用的 Node 函数创建一堆外部文件。我在以下位置公开发布了其中一些内容:
https://github.com/bolinfest/node-google-closure-latitude-experiment/tree/master/externs/node/v0.4.8
尽管最终,我认为这应该是社区驱动的事情,因为有很多功能需要记录。 (这也很烦人,因为一些 Node 函数有可选的中间参数而不是最后一个参数,这使得类型注释变得复杂。)我自己还没有开始这个运动,因为我们可以使用 Closure Complier 做一些工作来减少这种尴尬(见下文)。
假设您已经为 Node 命名空间 http
创建了 externs 文件。在我的系统中,我决定只要我需要 http
,我就会通过以下方式包含它:
var http = require('http');
虽然我没有在我的代码中包含 require()
调用。相反,我使用 Closure Compiler 的 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%"
],
这样,我的库代码从不调用 Node 的 require()
,但编译器容忍在我的代码中使用像 http
这样的东西,因为编译器将它们识别为外部人员。由于它们不是真正的外部人员,因此必须按照我的描述将它们放在前面。
最终,说完这个on the discussion list ,我认为更好的解决方案是为命名空间添加一个新的类型注释,如下所示:
goog.scope(function() {
/** @type {~NodeHttpNamesapce} */
var http = require('http');
// Use http throughout.
});
在这种情况下,externs 文件将定义 NodeHttpNamespace
,这样 Closure 编译器就可以使用 externs 文件对其属性进行类型检查。这里的不同之处在于,您可以根据需要命名 require()
的返回值,因为 http
的类型将是这种特殊的命名空间类型。 (为 $
识别“jQuery 命名空间”是一个类似的问题。)这种方法将消除为 Node 命名空间一致地命名局部变量的需要,并且将消除对巨大的 输出的需要-wrapper
在 plovr 配置中。
但那是题外话了......一旦我按照上面的描述进行了设置,我就有了一个 shell 脚本:
- 使用 plovr 在
RAW
模式下构建所有内容。 - 在 plovr 生成的文件上运行
node
。
使用 RAW
模式会导致所有文件的大量串联(尽管它也负责将 Soy 模板甚至 CoffeeScript 转换为 JavaScript)。不可否认,这让调试变得很痛苦,因为行号是无意义的,但到目前为止对我来说已经足够好了。 Closure Compiler 执行的所有检查都是值得的。
关于javascript - 让闭包编译器和 Node.js 发挥出色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34642380/