
Node.js 启用 ES 模块("type": "module")后,所有本地文件导入必须显式指定带扩展名的完整路径(如 ./config.js),否则会因路径解析失败导致 ERR_MODULE_NOT_FOUND 错误。
node.js 启用 es 模块(`"type": "module"`)后,所有本地文件导入必须显式指定带扩展名的完整路径(如 `./config.js`),否则会因路径解析失败导致 `err_module_not_found` 错误。
在 Node.js 中使用 ES 模块语法时,一个常见却极易被忽略的关键规则是:本地文件导入必须包含明确的文件扩展名(通常是 .js)。这与 CommonJS 的 require() 不同——后者支持自动解析 .js、.json 等扩展名,而 ES 模块规范(由 Node.js 严格实现)要求导入说明符(import specifier)必须是完整、有效的相对或绝对 URL 路径。因此,即使 config.js 和 server.js 处于同一目录,import config from './config' 也会失败,因为 './config' 并非合法的文件路径;Node.js 不会自动补全 .js 扩展名。
✅ 正确做法是:在 server.js 中将导入语句改为:
import express from 'express'; import sqlite3 from 'sqlite3'; import fetch from 'node-fetch'; import config from './config.js'; // ← 必须写 .js!
同样地,若你在 config.js 中使用命名导出(例如 export { config }),则对应导入也需保持一致并带上扩展名:
// config.js
const config = {
url: "my url string here",
port: 5000,
callbackURL: "another url here"
};
export { config };
// server.js
import { config } from './config.js'; // ← 命名导入 + .js 缺一不可
⚠️ 注意事项:
- ❌ 不要省略 ./ 前缀:import config from 'config' 会被解析为第三方包导入,而非本地文件;
- ❌ 不要依赖自动扩展名补全:import config from './config' 在 ES 模块下始终报错;
- ✅ 确保 package.json 中已声明 "type": "module"(你已正确配置);
- ✅ 文件名大小写需严格匹配(尤其在 Linux/macOS 系统下);
- ✅ 若使用 TypeScript 或构建工具(如 Vite、esbuild),其行为可能不同,但纯 Node.js 运行时以 .js 为准。
? 小技巧:为提升可维护性,可统一使用默认导出(export default config)+ 默认导入(import config from './config.js'),语义清晰且无需解构。同时建议在项目中启用 ESLint 规则 import/extensions(配合 node 解析器),自动提示缺失扩展名问题。
总结:这不是路径、命名或导出方式的问题,而是 ES 模块规范的硬性要求——本地模块导入必须带扩展名。修正 ./config → ./config.js 即可立即解决 ERR_MODULE_NOT_FOUND。











