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

问题描述 投票:0回答:2

所以,我今天花了相当多的时间尝试放置完全使用 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)

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

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

有人设法找到解决这个问题的方法吗?

node.js passenger es6-modules
2个回答
8
投票

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

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();

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

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


0
投票

我按照上面的步骤操作,唯一的区别是在我的 loader.cjs 文件中我使用了:

async function loadApp() {
  await import('./server.js')
}

loadApp()

server.js 文件位于根目录中。与 loader.cjs 相同的位置

© www.soinside.com 2019 - 2024. All rights reserved.