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

Dor*_*oro 11 javascript google-closure-compiler node.js

我有一个Node.js项目,我想用Closure Compiler编译.我不希望它在浏览器中运行/使用browserify.我主要想要类型检查的实用程序.我最初使用以下代码使编译器正常工作:

java -jar compiler.jar -W VERBOSE 
                       --language_in ECMASCRIPT5_STRICT 
                       --externs closure-externs.js 
                       --js="lib/**.js"
Run Code Online (Sandbox Code Playgroud)

其中closure-externs.js手动定义的变量和我是从Node.js的一个相当原始的方式使用该功能:

// closure-externs.js

/** @constructor */function Buffer(something){}
function require(path){}
var process = {};
[...]
Run Code Online (Sandbox Code Playgroud)

事实证明,这只能通过纯粹的运气来实现.文件之间没有依赖关系跟踪,因此您可能会遇到返回类型的情况,{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
Run Code Online (Sandbox Code Playgroud)

但这是失败的:

 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
Run Code Online (Sandbox Code Playgroud)

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

我知道还有其他标志--module,--common_js_module_path_prefix但是我不确定是否需要使用它们才能使其工作.我的Google-fu未能在这里找到关于正确咒语的任何答案.:(

Cha*_*rth 6

问题在于您希望编译器以某种方式识别某些require调用是内部的,即所需的模块应该由编译器作为源处理,而其他调用则是外部的,因此应该保持独立.目前没有办法处理这种情况.

解决方法

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

在这种情况下,您将完全省略require对外部模块的任何语句.编译器只处理具有内部require语句和模块的代码.编译之后,您将添加外部require语句:

标题JS将被添加

var crypto = require('crypto');
Run Code Online (Sandbox Code Playgroud)

要编译的来源

console.log(crypto);
Run Code Online (Sandbox Code Playgroud)

因为crypto在extern中声明,编译器将正确识别类型和符号名称.

别名需要通话

--process_common_js_modules指定时,编译器可以识别require的语句,并以类似的方式扩大他们的宏在其他语言的工作方式.通过别名require应保留为外部的语句,编译器将无法识别它们,因此不会扩展它们.

要编译的来源

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