使用 VM 模块运行 Node.js 脚本:“ReferenceError: require is not a function”

Dav*_*rds 0 virtual-machine require node.js

我正在编写自己的自定义 node.js 服务器。它现在处理静态页面、AJAX GET、POST 和 OPTIONS 请求(后者用于 CORS),但我知道我为运行服务器端 GET 和 POST 脚本选择的方法不是最佳的 - 官方 node.js文档指出,启动大量子 node.js 进程是一个坏主意,因为它是一种资源匮乏的方法。它有效,但我知道可能有更好的方法来实现相同的结果。

所以,我来到了 VM 模块。我的第一个想法是这将解决机器与子进程混乱的问题,并使我的服务器更具可扩展性。

有一个小问题。我的服务器端脚本,对于诸如目录列表和将结果发送回浏览器之类的任务,从几个require语句开始以加载所需的模块。

最终编写了读取脚本文件的代码并将其传递给 vm.Script() 后,我现在遇到了一个错误:

“参考错误:要求不是一个函数”

我后来了解到,这样做的原因是 VM 为脚本启动了一个裸 V8 执行环境,而不是一个独立的 node.js 执行环境。为了让我的想法奏效,我需要 VM 为我提供一个单独的沙盒 node.js 执行环境。我如何实现这一目标?

我的初步研究告诉我,我需要提供虚拟执行环境与node.js的全局自身的单独副本,以便需要发挥预期的作用。我刚才提供的理解是否正确?如果是这样,我需要采取哪些步骤来执行此任务?

rob*_*lep 5

我的初步研究告诉我,我需要为 VM 执行环境提供它自己单独的 node.js 全局副本,以便按预期使用函数

这是正确的runInNewContext,它不与“父”上下文共享全局变量(与 相对runInThisContext)。

为了require在您的脚本中提供功能,您可以将其作为函数传递。其他当地人也是如此,例如console

const vm = require('vm');

let sandbox = {
  require,
  console
};

vm.runInNewContext(`

let util = require('util');
console.log(util.inspect(util));

`, sandbox);
Run Code Online (Sandbox Code Playgroud)

除了require直接传递之外,您还可以传递一个函数来实现模块白名单(因此您可以控制允许脚本加载哪些模块)。