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。
必须显式声明类型:
注意以下几点:
立即学习“Java免费学习笔记(深入)”;
-
type="module"脚本自动启用严格模式,且this为undefined - 模块路径必须是相对或绝对 URL(不能是纯文件名),比如
./utils.js可以,utils.js会 404 - 模块脚本默认延迟执行(
defer行为),无需手动加defer - 无法通过
document.write或内联script使用import
export 写法差异直接影响 import 语法
导出方式决定导入时能否重命名、是否必须大括号、能不能解构——不是风格问题,是语法强制约束。
常见组合:
云模块_YunMOK网站管理系统采用PHP+MYSQL为编程语言,搭载自主研发的模块化引擎驱动技术,实现可视化拖拽无技术创建并管理网站!如你所想,无限可能,支持创建任何网站:企业、商城、O2O、门户、论坛、人才等一块儿搞定!永久免费授权,包括商业用途; 默认内置三套免费模板。PC网站+手机网站+适配微信+文章管理+产品管理+SEO优化+组件扩展+NEW Login界面.....目测已经遥遥领先..
- 命名导出(
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 'default') was not found。
Node.js 里用 ES6 模块要绕过两个硬性门槛
Node.js 从 v12.20+ 开始支持 ES6 模块,但默认仍走 CommonJS。想让 import 生效,必须满足其一:
- 文件扩展名为
.mjs(如index.mjs),且用node index.mjs运行 - 在
package.json中声明:"type": "module",此时所有.js文件都按 ES6 模块解析
但要注意:
- 一旦设为
"type": "module",就不能在同一个项目里混用require()(除非用createRequire动态加载) - Node.js 不支持裸模块名(
import _ from 'lodash'),必须写完整路径或配置exports字段 -
__dirname和__filename在 ES6 模块中不可用,要用import.meta.url配合file://协议解析路径
Vite/Webpack 等构建工具掩盖了模块解析细节
开发时写 import { debounce } from 'lodash' 能跑,不代表它真按标准模块规则加载——Vite 会把 lodash 的 ESM 版本转成本地模块,Webpack 则可能打包进 lodash-es 或降级为 CommonJS。
这意味着:
- 开发环境不报错 ≠ 浏览器原生能跑,部署前务必用
type="module"方式验证 - 动态
import()返回 Promise,可用于代码分割,但路径必须是字符串字面量(不能拼接变量) - Tree-shaking 是否生效,取决于导出是否为
export const形式而非export default { ... }对象
真正麻烦的不是语法,是模块解析链路太长:从你写的 import,到打包器重写,再到浏览器加载策略,任何一环没对齐就会静默失败或行为不一致。









