节点 --experimental-modules - 错误:找不到模块

Posted

技术标签:

【中文标题】节点 --experimental-modules - 错误:找不到模块【英文标题】:Node --experimental-modules - Error: Cannot find module 【发布时间】:2019-11-05 11:59:26 【问题描述】:

尝试导入本地文件时出现错误,但使用 npm 包时没有问题。

server.js

import express from 'express'
import next from 'next'

import apis from './src/server/api'

api.js

export default 
  ello: 'bye',
  jamie: 'hey'

启动应用程序

node --experimental-modules --inspect server.js

错误

For help, see: https://nodejs.org/en/docs/inspector
(node:20153) ExperimentalWarning: The ESM module loader is experimental.
internal/modules/esm/default_resolve.js:59
  let url = moduleWrapResolve(specifier, parentURL);
            ^

Error: Cannot find module '/var/www/goldendemon.hutber.com/src/server/api' imported from /var/www/goldendemon.hutber.com/server.js
    at Loader.resolve [as _resolve] (internal/modules/esm/default_resolve.js:59:13)
    at Loader.resolve (internal/modules/esm/loader.js:70:33)
    at Loader.getModuleJob (internal/modules/esm/loader.js:143:40)
    at ModuleWrap.<anonymous> (internal/modules/esm/module_job.js:43:40)
    at link (internal/modules/esm/module_job.js:42:36) 
  code: 'ERR_MODULE_NOT_FOUND'

【问题讨论】:

【参考方案1】:

或者像我一样,在你的源代码处理 ES 样式模块导入或其他一些非标准 javascript 代码(例如 TypeScript)在 Node.js 上的那一刻使用转译。作为参考,请参阅我编写的这个快速 bash 脚本,在我的 Node 项目中另存为 .script/run-it.sh

#!/bin/bash

script=$1
out_path==/tmp/$script-out.js
npx esbuild --platform=node --bundle --outfile=$out_path $script
node $out_path 

我将它作为运行脚本添加到我的package.json

"scripts": 
    "test": "sst test",
    "start": "sst start",
    "build": "sst build",
    "deploy": "sst deploy",
    "remove": "sst remove",
    "run-it": "./.script/run-it.sh"
  ,

还有我的目标脚本 (import-test.js),我想作为 JavaScript 代码发出/转译:

import  default as myImport  from './lib/index.js'
console.log(myImport)

现在我运行它:

$ npm run run-it ./import-test.js 

> my-nop@0.1.0 run-it /Users/jmquij0106/git/a-rebalancing-act
> ./.script/run-it.sh "./import-test.js"

[Function: main]

无论何时在 Node.js 上处理 ES 模块,底线都会让您免于痛苦,只需发出符合 CommonJS 的代码,请参阅 this comment/issue。

【讨论】:

【参考方案2】:

如果其他人有这个问题,我正在回答我自己的问题。

事实证明,在实验模式下,您需要定义带有扩展名的完整路径。所以我尝试导入index.js 认为它会知道。

修复它:

import express from 'express'
import next from 'next'
import api from './src/server/api/index.js'

【讨论】:

天哪,这是具有挑战性的......添加 .js 扩展是让我受不了的原因。您的回答有助于诊断! 你如何使用 typescript 进行这项工作?当我运行tsc 时,我的文件是使用不带扩展名的导入编译的。 对于 TypeScript(使用 Node 12),请参阅 Mateus 的回答 (#answer-57558982)。在使用 node 运行脚本时使用此 (--es-module-specifier-resolution=node) 选项将解决问题,但您可能会遇到其他小问题(例如,__dirname 未定义)。 我认为 Node 实验模式太麻烦了,不能只运行一个简单的测试脚本来处理 ESM 样式的导入,所以我只好转而使用 esbuild。我写了这个简短的 bash 脚本来完成这个:#!/bin/bash script=$1 out_path==/tmp/$script-out.js npx esbuild --platform=node --bundle --outfile=$out_path $script node $out_path 嘿,不确定它是否能解决您的问题,但试一试。检查这个Github comment 和这个Node Docs。总结一下,可以把"#api": "./src/server/api/index.js"加到你的package.json["imports"]里面,导入可以用import api from '#api'解决【参考方案3】:

在节点 12 上,您有 2 个选项:

    在 package.json、实验模块上使用 type="module" 并指定具有特定分辨率的扩展,如下所示: node --experimental-modules --es-module-specifier-resolution=node src/index

    或不使用说明符分辨率。请记住,您必须在每个位置指定文件的扩展名。

【讨论】:

请注意,尚不清楚--es-module-specifier-resolution 是否会继续存在。这也意味着代码与其他 ES 模块运行时(例如浏览器)不兼容。 已转换为:--experimental-specifier-resolution=node 看到 here (careful, theres a typo in that post)【参考方案4】:

如果您使用 .mjs 扩展名命名模块文件,它也应该可以工作。此外,还提到了启用 ESM 的其他方法here。

当 Node.js 作为初始输入传递给 node 或被 ES 模块代码中的 import 语句引用时,Node.js 会将以下内容视为 ES 模块:

以 .mjs 结尾的文件。

以 .js 结尾的文件或无扩展名文件,当最近的父 package.json 文件包含一个值为“module”的***字段“type”时。

作为参数传入 --eval 或 --print 的字符串,或通过 STDIN 管道传输到节点,带有标志 --input-type=module。

【讨论】:

以上是关于节点 --experimental-modules - 错误:找不到模块的主要内容,如果未能解决你的问题,请参考以下文章

节点 --experimental-modules,请求的模块不提供名为的导出

如何在 Typescript 输出中使用 node --experimental-modules

nodejs12 支持es6模块加载

Node.js 宣布正式支持 ECMAScript modules

Nodejs中ES Modules如何操作运用?本文详解

Node.js 8.5 带来哪些新特性