加 type="module" 后仍报 Cannot use import statement outside a module,说明脚本未被识别为模块:常见原因包括未加 type="module"、内联 script 同时带 src、外部 JS 未被显式声明为模块,且 file:// 协议下 import 必报 CORS 错误,必须用 HTTP 服务。

直接加 type="module" 就能启用 ES 模块,但不配好路径、不跑在 HTTP 服务上、不改写 import 语法,90% 的人会卡在白屏或控制台报错。
为什么加了 type="module" 还报 Cannot use import statement outside a module
这个错误只说明一件事:你写了 import,但脚本没被当成模块执行。常见原因有三个:
- 用了普通
<script></script>标签(没写type="module"),却在里头写import—— 浏览器根本不认识这语法 - 写了
<script type="module"></script>,但它是内联的,同时又带src属性(比如<script type="module" src="main.js">console.log(1)</script>)—— 内联内容会被完全忽略,console.log(1)不会执行 - 脚本是外部文件(
src="main.js"),但main.js里用了import,而它自己没被声明为模块(即它的加载者没加type="module")—— 模块行为不会“传染”,必须每一层都显式声明
本地双击打开 HTML 文件时,import 总是 CORS 错误
这是最常被忽略的硬性限制:ES 模块的 import 必须通过 HTTP(S) 协议加载,file:// 协议下所有相对路径导入都会被浏览器拒绝,并报 Cross-Origin Request Blocked。
- 不能双击 HTML 文件运行 —— Chrome/Firefox/Safari 全部拦截
- 必须启动一个最小 HTTP 服务,比如:
npx serve(需装 Node)、python3 -m http.server 8000(Python 自带) - 路径必须是相对 URL(以
./或../开头)或绝对 URL(/js/utils.js或https://cdn.skypack.dev/lodash),不能省略扩展名:import './utils.js'✅,import './utils'❌ - 裸导入(
import 'lodash')不合法,除非你配了<script type="importmap"></script>
多个 type="module" 脚本之间变量不共享,怎么办
这是模块设计的本意,不是 bug。传统 <script></script> 共享 window,而每个 type="module" 有独立作用域,彼此看不到对方声明的变量或函数。
- 别指望在
<script type="module" src="a.js"></script>里定义const foo = 1,然后在另一个<script type="module" src="b.js"></script>里直接用foo—— 它就是不存在 - 要共享逻辑,必须走标准模块流程:在
a.js中export const foo = 1,在b.js中import { foo } from './a.js' - 如果老代码全是 IIFE 或全局挂载(如
window.utils = {...}),别强行塞进type="module"—— 先封装成export,再统一import,否则会掉进“一半模块、一半全局”的陷阱
type="module" 脚本里 document.currentScript 是 undefined
模块脚本中 document.currentScript 始终为 undefined,因为模块加载机制和执行时机与传统脚本完全不同。
- 别依赖它来动态读取当前脚本的
src或自定义data-属性 - 如果需要类似能力(比如根据按钮 data 属性加载不同模块),改用
import()动态导入:const mod = await import(`./features/${name}.js`) - 注意:
import()只能在模块上下文中调用 —— 父级<script type="module"></script>必须存在,否则报错 -
import()返回 Promise,支持try/catch,适合做错误降级(比如加载失败时显示提示)
真正麻烦的不是语法,而是路径、协议、作用域这三道关卡。本地开发时少双击,多开终端;写 import 时多打 .js,少猜路径;迁移旧项目时别想着“一键改 type”,先抽离 export,再逐个 import。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











