浏览器需加type="module"且import路径须为相对/绝对/完整URL;Node需.mjs或"type":"module";default与named export导入方式不同;import()返回Promise,支持动态路径但需手动处理URL。

浏览器中直接用 import 会报 Failed to resolve module specifier 错误——因为 ES6 模块默认不支持裸路径,且必须在 type="module" 的脚本上下文中运行。
怎样让浏览器正确加载 ES6 模块
核心是两件事:声明模块类型、遵守模块解析规则。
- HTML 中的
标签必须加上type="module"属性,否则import/export语法会直接报错 - 所有
import路径必须是相对路径(如./utils.js)、绝对路径(如/src/main.js)或完整 URL(如https://cdn.skypack.dev/lodash-es),不能写成import { foo } from 'lodash' - 模块脚本默认是
defer行为:不会阻塞 HTML 解析,且按顺序执行,无需手动处理加载时机
Node.js 里用 import 报 Cannot use import statement outside a module
这是 Node 默认把 .js 文件当 CommonJS 处理。要启用 ES 模块,得满足其一:
- 文件扩展名改为
.mjs(最简单,无需配置) - 在
package.json中显式声明"type": "module"(注意:此后所有 .js 都按 ES 模块处理,require()会失效) - 启动时加
--input-type=module参数(仅适用于字符串输入,不适合日常开发)
另外,Node 不支持裸包名导入(如 import { debounce } from 'lodash'),必须用完整路径或借助工具(如 node --experimental-import-meta-resolve 或打包器)。
立即学习“Java免费学习笔记(深入)”;
export default 和具名 export 混用要注意什么
一个模块可以同时有默认导出和具名导出,但导入方式必须匹配:
-
export default function foo() {}→ 必须用import foo from './foo.js'(名字可任意) -
export function bar() {}→ 必须用import { bar } from './foo.js'(名字必须一致,或重命名:import { bar as myBar }) - 混合时不能写成
import foo, { bar } from './foo.js'—— 这是合法语法,但容易混淆;更推荐拆成两个import语句,逻辑更清晰
常见坑:试图用 import * as ns from './foo.js' 获取默认导出,结果 ns.default 是 undefined —— 因为默认导出不会自动挂到命名空间对象上,除非模块明确写了 export default + export *。
动态 import() 的实际用途和限制
import() 是函数调用,返回 Promise,适合按需加载、条件加载或打破循环依赖。
- 路径可以是表达式:
import(`./pages/${page}.js`),但不能是纯变量(V8 会静态分析失败) - 不支持在顶层作用域外使用(比如函数内可以,但不能放在
if块顶层之外的任意位置) - 打包工具(如 Webpack、Vite)能识别它并自动做代码分割;但原生浏览器不预加载,首次调用才有网络请求
- 错误捕获必须用
.catch()或try/catch,否则会变成未处理拒绝(unhandled rejection)
真正麻烦的是路径拼接——浏览器不支持 Node 风格的 __dirname 或 import.meta.url 自动解析相对路径,常需要手动补全协议或 base URL。










