Chr*_* W. 106 javascript commonjs node.js
有一些第三方Javascript库具有我想在Node.js服务器中使用的一些功能.(具体来说,我想使用我发现的QuadTree javascript库.)但这些库只是简单的.js文件而不是"Node.js库".
因此,这些库不遵循exports.var_nameNode.js对其模块所期望的语法.据我了解,这意味着当你这样做module = require('module_name');或者module = require('./path/to/file.js');你最终会得到一个没有公共可访问功能的模块等.
我的问题是"我如何将任意javascript文件加载到Node.js中,以便我可以利用它的功能,而不必重写它,以便它可以做到exports?"
我对Node.js很新,所以如果我对它的工作原理有一些明显的漏洞,请告诉我.
编辑:研究更多东西,我现在看到Node.js使用的模块加载模式实际上是最近开发的加载Javascript库的标准的一部分,称为CommonJS.它在Node.js的模块文档页面上说明了这一点,但直到现在我才错过了.
可能最终我的问题的答案是"等到你的图书馆的作者开始写一个CommonJS界面或者做你自己该死的自己."
Chr*_* W. 79
以下是我认为这种情况的"最正确"答案.
假设您有一个名为的脚本文件quadtree.js.
您应该构建node_module具有此类目录结构的自定义...
./node_modules/quadtree/quadtree-lib/
./node_modules/quadtree/quadtree-lib/quadtree.js
./node_modules/quadtree/quadtree-lib/README
./node_modules/quadtree/quadtree-lib/some-other-crap.js
./node_modules/quadtree/index.js
Run Code Online (Sandbox Code Playgroud)
./node_modules/quadtree/quadtree-lib/目录中的所有内容都是第三方库中的文件.
然后你的./node_modules/quadtree/index.js文件将从文件系统加载该库,并正确地导出东西.
var fs = require('fs');
// Read and eval library
filedata = fs.readFileSync('./node_modules/quadtree/quadtree-lib/quadtree.js','utf8');
eval(filedata);
/* The quadtree.js file defines a class 'QuadTree' which is all we want to export */
exports.QuadTree = QuadTree
Run Code Online (Sandbox Code Playgroud)
现在您可以quadtree像任何其他节点模块一样使用您的模块......
var qt = require('quadtree');
qt.QuadTree();
Run Code Online (Sandbox Code Playgroud)
我喜欢这种方法,因为不需要更改第三方库的任何源代码 - 所以它更容易维护.升级所需要做的就是查看源代码并确保仍在导出正确的对象.
Dav*_*ver 73
有一个比使用更好的方法eval:vm模块.
例如,这是我的execfile模块,它path在任一context或全局上下文中评估脚本:
var vm = require("vm");
var fs = require("fs");
module.exports = function(path, context) {
context = context || {};
var data = fs.readFileSync(path);
vm.runInNewContext(data, context, path);
return context;
}
Run Code Online (Sandbox Code Playgroud)
它可以像这样使用:
> var execfile = require("execfile");
> // `someGlobal` will be a global variable while the script runs
> var context = execfile("example.js", { someGlobal: 42 });
> // And `getSomeGlobal` defined in the script is available on `context`:
> context.getSomeGlobal()
42
> context.someGlobal = 16
> context.getSomeGlobal()
16
Run Code Online (Sandbox Code Playgroud)
其中example.js包括:
function getSomeGlobal() {
return someGlobal;
}
Run Code Online (Sandbox Code Playgroud)
这种方法的最大优点是你可以完全控制执行脚本中的全局变量:你可以传入自定义全局变量(via context),并且将添加脚本创建的所有全局变量context.调试也更容易,因为将使用正确的文件名报告语法错误等.
Chr*_*iss 30
最简单的方法是:eval(require('fs').readFileSync('./path/to/file.js', 'utf8'));
这非常适合在交互式shell中进行测试.
AFAIK,确实是必须加载模块的.但是,exports您可以将所有导出的函数添加到对象上this(而不是将其作为全局对象).
因此,如果您想保持其他库兼容,您可以这样做:
this.quadTree = function () {
// the function's code
};
Run Code Online (Sandbox Code Playgroud)
或者,当外部库已经有自己的命名空间时,例如jQuery(不是你可以在服务器端环境中使用它):
this.jQuery = jQuery;
Run Code Online (Sandbox Code Playgroud)
在非Node环境中,this将解析为全局对象,从而使其成为全局变量......它已经存在.所以它不应该破坏任何东西.
编辑:James Herdman 为初学者提供了关于node.js 的精彩文章,其中也提到了这一点.