type="module"是启用es模块的硬性前提,它强制切换执行环境:启用严格模式、作用域隔离、默认defer、cors校验及显式路径要求(如./utils.js),本地file://协议下必然失败。

必须加 type="module",否则 import/export 语法直接报错 —— 这不是可选项,是硬性前提。
为什么加了 type="module" 后脚本行为彻底变了
浏览器一看到 type="module",就切换到 ES 模块加载器,不再走传统脚本流程。它会:
- 自动启用严格模式(不用写
"use strict") - 把整个脚本当作模块作用域处理:顶层
let/const/function不会挂到window上 - 默认等同于加了
defer:HTML 解析完才执行,且多个type="module"按顺序串行执行 - 强制校验 CORS:本地双击打开 HTML(
file://协议)必然失败,报错Access to script at 'file://' from origin 'null' has been blocked by CORS policy
import 路径必须带 .js 后缀,且区分大小写
原生模块不支持“路径省略扩展名”这种便利。下面这些写法都会报 Failed to resolve module specifier:
-
import { foo } from './utils'❌(缺.js) -
import { foo } from './Utils.js'❌(Linux/macOS 下文件名大小写不匹配) -
import { foo } from 'lodash'❌(裸导入不被原生支持)
正确写法只有:
-
import { foo } from './utils.js'✅ -
import mod from '/src/main.js'✅(绝对路径从站点根目录算起) -
import('./lazy.js').then(...)✅(动态import()同样要带后缀)
模块路径是相对于当前模块文件,不是 HTML 文件
比如 index.html 里写了:<script type="module" src="./src/main.js"></script>,那么 main.js 中的 import { helper } from './lib/utils.js' 是从 ./src/lib/utils.js 去找,而不是从 index.html 所在目录开始找。
- 相对路径(
./、../)始终以当前模块文件 URL 为基准 - 绝对路径(
/xxx.js)从服务器根路径解析,和 HTML 放在哪无关 - 没有“基于 HTML 的相对路径”这种东西 —— 这点容易误判,尤其在重构目录结构时
最常卡住的地方不是语法写错,而是本地开发没起服务、路径少写 .js、或大小写拼错。只要记住:模块加载是 URL 寻址过程,不是文件系统路径拼接,问题就清晰多了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











