在浏览器中直接运行原生ESM需满足:①script标签设type="module";②import路径必须带扩展名且为相对/绝对URL或完整URL;③须通过HTTP服务器访问(禁用file://协议)。

在浏览器中直接运行原生 ES Modules(ESM)代码,不需要构建工具,只需满足两个核心条件:使用 <script type="module"> 标签,并确保模块路径符合浏览器的模块解析规则(如带扩展名、相对或绝对 URL)。
1. 基础写法:用 type="module" 声明
普通 <script> 是 CommonJS 或脚本模式,而 ESM 必须显式声明:
<script type="module">
import { foo } from './utils.js';
console.log(foo());
</script>
注意:这类 script 默认是 defer 行为(不阻塞 HTML 解析,且按顺序执行),且具有顶层 await、不能访问 var 声明的变量等 ESM 特性。
2. 模块路径必须合法(关键易错点)
浏览器对 ESM 的 import 路径要求比 Node.js 严格,常见限制包括:
- 不能省略扩展名(
import './utils'❌,必须写import './utils.js'✅) - 不能用纯裸名(
import 'lodash'❌,浏览器不支持包名自动解析) - 支持相对路径(
./、../)、绝对路径(/assets/main.js)、完整 URL(https://cdn.jsdelivr.net/npm/vue@3/dist/vue.esm-browser.js)
3. 处理依赖链和顶层 await
ESM 支持顶层 await,可直接在模块最外层等待 Promise:
<script type="module">
const res = await fetch('/api/data.json');
const data = await res.json();
console.log(data);
</script>
但注意:含顶层 await 的模块会阻塞其所有静态导入的后续执行,适合初始化逻辑。
4. 跨域与 MIME 类型要求
如果模块文件来自其他域名(如 CDN),需满足:
- 服务端返回
Content-Type: application/javascript(不是text/plain) - 响应头包含
Cross-Origin-Resource-Policy: cross-origin或 CORS 头(如Access-Control-Allow-Origin: *)
本地双击打开 HTML 文件(file:// 协议)时,大多数浏览器会因跨域限制拒绝加载模块——务必用本地服务器(如 npx serve、python3 -m http.server)启动。
type="module" + 合法路径(带 .js)+ HTTP 服务环境。不需要 Babel、不需要打包,现代浏览器(Chrome 61+、Firefox 60+、Safari 11+)均原生支持。


















