【问题标题】:Best way to share JS between browser and node.js when using Google Closure compiler使用 Google Closure 编译器时在浏览器和 node.js 之间共享 JS 的最佳方式
【发布时间】:2011-12-23 00:45:59
【问题描述】:

我正在浏览器和运行 node.js 的服务器之间开发一个网络应用程序。我现在正在共享很多代码,但是当我实际部署它时,我希望客户端只获取客户端特定的代码。我现在的选择是:

1.) 使用继承实现任何浏览器/node.js 差异。我已经在几个地方尝试过这个,我最终得到了很多非常非常基本的类,它们的父类通常只是部分专门化了一个功能。这不是我非常喜欢的风格,因为当你试图找出实际发生的事情时,它意味着很多间接性。

2.) 在全局范围内定义一个类似 IS_BROWSER 的常量,然后在我需要更改浏览器与 node.js 上的代码路径时检查它。然后闭包编译所有具有高级优化的 js 以删除浏览器上的死代码(设置 IS_BROWSER = true)。假设我做了我需要做的任何事情来在闭包编译器中进行高级优化,这种方法是否有任何问题?

3.) ??我愿意接受建议。

【问题讨论】:

  • 您使用的是什么 JavaScript 库?相当多的 JavaScript 库将为您抽象出浏览器和 node/rhino 之间的差异。按照你的 #2 使用全局常量也很有效,但我相信最好的方法是使用抽象所有这些的库。
  • 许多差异实际上是应用程序逻辑差异,因此它们不会被库抽象掉。
  • 我很好奇,浏览器环境与无头服务器环境会有什么逻辑差异? AFAIK,它们都支持环境中的大多数相同功能。如果对 CPU 使用率、线程等有顾虑,那么我认为使用“has.js”库进行环境特征检测可能是未来最灵活的方式。
  • @StephenChung:您能否举一个“库将为您抽象出浏览器和 node/rhino 之间的差异”的示例?
  • @bukzor,例如 Dojo 支持大多数浏览器、rhino 和 node(虽然我不确定 node 支持是否正式推出)。

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


【解决方案1】:

如果您使用高级编译,则应删除任何未使用的代码;如果您正确使用编译器的导出系统,您的客户端代码未调用的任何服务器端代码都不会出现在客户端代码的编译版本中。

您可以将所有代码写在一个大块中,然后为您的客户添加一个文件,其内容如下

goog.require('my.client.app');
goog.exportSymbol('my.app.entryPoint', my.client.app.entryPoint);

编译后的代码不会包含任何不在my.client.app.entryPoint 调用树中的内容。同样,如果您的编译仅导出服务器入口点,则客户端代码将被排除在外。

上述风格用于编写脚本以提供一些函数,然后被内联脚本调用;要将整个事情变成一个脚本,您可以做一些更简单的事情:

goog.require('my.client.app');
my.client.app.entryPoint();

要验证您的编译输出中没有出现大量死代码,您可以使用以下代码:ScriptCover

【讨论】:

  • 这个问题是关于node.js和闭包编译器的。我没有看到任何关于closure-library(cl) 的提及,如果没有第三方(第四?)方库的大量帮助,cl 将无法在 node.js 下工作,目前这些库都不是生产质量的。跨度>
  • 好点。我用 Closure 库风格编写了示例代码,但这完全没有必要。
  • 当你说“这是不必要的”时,这意味着还有另一种方法。有吗?
  • 编译器以特殊方式处理goog.requiregoog.exportSymbol,但是您通过require 添加的任何代码都可以添加到您要编译的内容之前,并且可以替换exportSymbol在浏览器中使用this["varName"] = varValuethis 希望默认为全局或模块范围)或window["varName"] = varValue。如果您通过其名称的字符串访问属性,编译器将不会重命名该访问。为了保证以 .fieldName 样式访问的字段可以使用该名称访问,您必须使用 exportSymbol
  • 也就是说,如果 base.js(定义 requireexportSymbol)不能与 node.js 一起使用,我会感到惊讶;他们至少定义并使用“我在浏览器中吗?”功能,它们不接触,例如 DOM 功能。
猜你喜欢
  • 2011-03-14
  • 2016-11-15
  • 2016-11-03
  • 1970-01-01
  • 2012-08-27
  • 2021-12-31
  • 2020-09-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多