ES6模块运行需满足三环境约束:浏览器须加type="module"且路径为URL;Node.js需.mjs扩展名或package.json设"type":"module";构建工具会改写import行为导致开发与生产不一致。
ES6 模块(import/export)不是“用不用”的问题,而是“怎么在真实环境中跑起来”的问题——浏览器原生支持但有严格限制,Node.js 默认不识别 .mjs 以外的 import,Webpack/Vite 等工具又会改写行为。直接写 import 却报错,大概率卡在这三个地方。
import 必须加 type="module"
HTML 中引用 ES6 模块脚本时, 会被当普通脚本执行,哪怕里面写了 import 也会报 Uncaught SyntaxError: Cannot use import statement outside a module。
必须显式声明类型:
注意以下几点:
type="module" 脚本自动启用严格模式,且 this 为 undefined
./utils.js 可以,utils.js 会 404defer 行为),无需手动加 defer
document.write 或内联 script 使用 import
export 写法差异直接影响 import 语法导出方式决定导入时能否重命名、是否必须大括号、能不能解构——不是风格问题,是语法强制约束。
常见组合:
export const foo = 1 或 export { foo })→ 必须用 import { foo },名字必须一致,可重命名:import { foo as bar }
export default function() {})→ 用 import anything from './mod',名字随意,且不能加花括号default + 多个命名)→ 可同时写:import def, { named1, named2 } from './mod'
import * as mod from './mod',此时 mod.default 访问默认导出,mod.named 访问命名导出错误示例:对默认导出写 import { default } from './mod' 会报 export 'default' (imported as 'def。
Node.js 从 v12.20+ 开始支持 ES6 模块,但默认仍走 CommonJS。想让 import 生效,必须满足其一:
.mjs(如 index.mjs),且用 node index.mjs 运行package.json 中声明:"type": "module",此时所有 .js 文件都按 ES6 模块解析但要注意:
"type": "module",就不能在同一个项目里混用 require()(除非用 createRequire 动态加载)import _ from 'lodash'),必须写完整路径或配置 exports 字段__dirname 和 __filename 在 ES6 模块中不可用,要用 import.meta.url 配合 file:// 协议解析路径开发时写 import { debounce } from 'lodash' 能跑,不代表它真按标准模块规则加载——Vite 会把 lodash 的 ESM 版本转成本地模块,Webpack 则可能打包进 lodash-es 或降级为 CommonJS。
这意味着:
type="module" 方式验证import() 返回 Promise,可用于代码分割,但路径必须是字符串字面量(不能拼接变量)export const 形式而非 export default { ... } 对象真正麻烦的不是语法,是模块解析链路太长:从你写的 import,到打包器重写,再到浏览器加载策略,任何一环没对齐就会静默失败或行为不一致。