你如何在Closure Compiler中将node_modules定义为extern?

我有一个Node.js项目,我想用Closure编译器进行编译。 我不希望它运行在浏览器/使用browserify。 我主要希望types检查的效用。 我最初得到编译器使用以下正确工作:

java -jar compiler.jar -W VERBOSE --language_in ECMASCRIPT5_STRICT --externs closure-externs.js --js="lib/**.js" 

其中closure-externs.js手动定义了我从Node.js中使用的variables和函数:

 // closure-externs.js /** @constructor */function Buffer(something){} function require(path){} var process = {}; [...] 

事实certificate,这只是通过运气好运。 在文件之间没有依赖关系跟踪,所以你可以有返回types{Foo} ,编译器会抱怨它不存在(取决于机器,取决于编译顺序)。 然后我发现我所做的一切都是错误的,应该使用--process_common_js_modules这样编译器就会在require("foo")地方执行依赖关系跟踪。 我目前正在调用编译器像这样:

 java -jar compiler.jar -W VERBOSE --language_in ECMASCRIPT5_STRICT --externs externs/fs.js --js="lib/**.js" --process_common_js_modules --common_js_entry_module app.js 

但是这是失败的:

  ERROR - required entry point "module$crypto" never provided ERROR - required entry point "module$dgram" never provided ERROR - required entry point "module$extend" never provided ERROR - required entry point "module$fs" never provided ERROR - required entry point "module$net" never provided ERROR - required entry point "module$q" never provided 

其中一些模块是Node.js(例如fs )的本地模块,而其他模块则包含在node_modulesq 。 我不想通过编译器运行这些外部模块,所以我知道我需要为它们设置externs文件。 我知道对于常见的Node.js externs,有https://github.com/dcodeIO/node.js-closure-compiler-externs ,而且我知道如何在编译器上调用它们,但由于某种原因,当我做类似--externs externs/fs.js module$fs的错误依然存在。 我究竟做错了什么?

我知道还有其他的标志,如 – 模块和--common_js_module_path_prefix但我不知道是否需要使用它们来得到这个工作与否。 我的Google-fu在这里没有提出任何正确的咒语的答案。 🙁

问题是你希望编译器能够以某种方式认识到某些require调用是内部的,即所需的模块应该由编译器作为源处理,而其他模块则是外部的,所以应该单独保留。 目前没有一种好的办法来处理这种情况。

解决方法

使用后处理添加外部需求语句

在这种情况下,您可以完全省略任何对外部模块的require语句。 编译器只会处理带有内部require语句和模块的代码。 编译之后,你可以预先configuration外部的require语句:

标题JS将被预置

 var crypto = require('crypto'); 

来源编译

 console.log(crypto); 

由于crypto是在extern中声明的,因此编译器将正确识别types和符号名称。

别名需要调用

当指定了--process_common_js_modules ,编译器会识别require语句,并以与macros在其他语言中工作的方式类似的方式进行扩展。 通过混淆应该保持外部的require语句,编译器将不会识别它们,因此不会扩展它们。

来源编译

 var externalRequire = require; /** @suppress {duplicate} this is already defined in externs */ var crypto = externalRequire('crypto'); console.log(crypto)