Node JS (cpanel) 错误:我收到错误 [ERR_REQUIRE_ESM]:必须使用 import 来加载 ES 模块

Ved*_*ran 5 passenger node.js es6-modules

因此,今天我花了相当多的时间尝试放置完全使用 ESM(模块)的 NodeJS 应用程序,并且我已通过 cPanel 将其部署在使用 Node v. 14.20.1 的服务器上。我不断收到错误:

 App 1153856 output: internal/modules/cjs/loader.js:948
App 1153856 output:     throw new ERR_REQUIRE_ESM(filename);
App 1153856 output:     ^

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /<serverlocation>/app.js
    App 1153856 output:     at new NodeError (internal/errors.js:322:7)
    App 1153856 output:     at Module.load (internal/modules/cjs/loader.js:948:11)
    App 1153856 output:     at Function.Module._load (internal/modules/cjs/loader.js:790:12)
    App 1153856 output:     at Module.require (internal/modules/cjs/loader.js:974:19)
    App 1153856 output:     at Module.require (/opt/cpanel/ea-ruby27/root/usr/share/passenger/helper-scripts/node-loader.js:80:25)
Run Code Online (Sandbox Code Playgroud)

所有文件都作为模块编写,我在任何地方都没有“require()”。

由于 Node 从 v14 开始完全支持 JS 模块,我大胆猜测我正在使用的托管服务器(及其 NodeJS 的 Passenger)正在使用一个加载器,该加载器在调用我的应用程序时使用“require()”。 js 文件。我尝试了多种解决方案,我什至将我的app.js文件切换为CommonJS类型,但随后它要求我将所有其他文件也切换为CJS,这太麻烦了。

有没有人设法找到这个问题的正确解决方案?

小智 11

对于任何试图解决此问题的人,这就是我解决它的方法:

1- 创建加载器脚本:不一定与应用程序的主 app.js 文件位于同一文件夹中,但这是我创建它的位置。称其为 loader.cjs 之类的名称。如果你的 package.json 中有 "type": "module" ,那么扩展名为 .cjs 就很重要。正如您可能已经猜到的,这将是您应用程序的新主目录。由于乘客的加载程序存在 ES 模块问题,因此只需让它加载 commonjs 文件即可。

2- 动态导入app.js:您知道您仍然可以在commonjs 文件中加载ES 模块吗?你只需要一点额外的努力就能做到这一点。显然,ES 模块是异步加载的,这对于同步的 commonjs 文件来说效果不佳。这就是你首先遇到这个问题的原因,对吧?因此,解决方案是:动态导入。就像异步函数一样,将 ES 模块的导入视为承诺。我不太喜欢使用 .then(),所以我选择了 wait:

async function loadApp() {
    await import("/path/to/app.js");
}

loadApp();
Run Code Online (Sandbox Code Playgroud)

3-重命名你的app.js的扩展名:我不完全知道为什么这是必要的,但我收到了“无法找到/path/to/app.mjs”的错误,所以我将其更改为这样。然后就成功了。您可以将上一点路径中的文件名保留为“app.js”,导入仍然会正确查找“app.mjs”;

可能有更有效的方法来做到这一点,但这就是我的两颗大脑所能想出的。希望它也能帮助其他人。

  • 嗯,你绝对帮了我的忙。它就像一个魅力,谢谢! (2认同)