javascript - 让闭包编译器和 Node.js 发挥出色

标签 javascript node.js require google-closure-compiler

有没有同时使用node.js和closure-compiler(简称CC)的项目?

官方的 CC 建议是一起编译应用程序的所有代码,但是当我编译一些包含 require("./MyLib.js") 的简单 node.js 代码时,该行直接放入输出中,但在该上下文中没有任何意义。

我看到几个选项:

  1. 将整个应用程序编码为一个文件。这通过避免它解决了问题,但不利于维护。
  2. 假设所有文件将在执行前连接起来。这再次避免了问题,但更难实现未编译的 Debug模式。
  3. 我想让 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 脚本:

  1. 使用 plovr 在 RAW 模式下构建所有内容。
  2. 在 plovr 生成的文件上运行 node

使用 RAW 模式会导致所有文件的大量串联(尽管它也负责将 Soy 模板甚至 CoffeeScript 转换为 JavaScript)。不可否认,这让调试变得很痛苦,因为行号是无意义的,但到目前为止对我来说已经足够好了。 Closure Compiler 执行的所有检查都是值得的。

关于javascript - 让闭包编译器和 Node.js 发挥出色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34642380/

相关文章:

javascript - 描述符可以更改 Typescript 中的类型吗?

javascript - 如何从 mocha.opts 文件中正确地要求模块

JavaScript,需要 var

node.js - 我应该如何从 node_modules 文件夹外部有效地要求模块?

javascript - 单击外部链接时隐藏谷歌地图的标记,仅显示其相应的标记

javascript - 在 Javascript 中执行多个 ajax 调用

javascript - jQuery .height 方法无法在 iOS Safari 中设置高度

javascript - 我怎样才能 'fire and forget'一个JS函数? (不要等待返回)

Javascript Nodejs 值未插入数组

javascript - 我应该使用 process.nextTick 还是 setImmediate 进行异步迭代?