dynamic import() 必须在 type="module" 脚本中执行,因它是ES模块表达式;普通 script 会报错,且路径需被构建工具静态分析,部署时注意 base 配置与网络请求路径一致性。

dynamic import() 为什么不能写在 script 标签里直接调用
因为 dynamic import() 是一个表达式,必须在模块上下文(type="module")中执行,普通 <script> 默认是 script 模式,会直接报 Unexpected token 'import'。
- 必须把调用它的 JS 代码放进
<script type="module">中,哪怕只有一行import('./foo.js') - HTML 里不能写
<script>import('./a.js')</script>—— 这不是语法错误,而是根本不会被解析为 import 表达式 - 如果项目没开 ES 模块支持(比如旧版 Webpack/Vite 配置没设
build.target),即使写了type="module",也可能因转译失败导致import()被忽略或报错
HTML 中触发 dynamic import() 的三种可靠入口点
不能靠 HTML 直接“声明”,得靠 JS 主动发起。最常用且可控的有三个位置:
- 放在
<script type="module">内部,作为初始化逻辑的一部分:document.getElementById('btn').addEventListener('click', () => { import('./chart.js').then(m => m.render()) }) - 在已加载的模块中导出一个函数,由外部非模块脚本调用(适合渐进式迁移):
// main.mjs export function loadEditor() { return import('./editor.js') } // index.html 中: <script> // 等 main.mjs 加载完后调用 window.loadEditor?.().then(m => m.init()) </script> - 用
async函数包装,在页面空闲时预加载(配合requestIdleCallback或setTimeout(..., 0)),避免阻塞首屏渲染
import() 返回 Promise,但 catch 不住网络错误?
能 catch,但要注意:它只捕获模块解析和加载阶段的失败(如 404、MIME 类型错误、语法错误),不捕获模块内部运行时报错(比如 ReferenceError)。
- 常见假象:
import('./bad.js').catch(e => console.log(e))没输出 → 实际是模块加载成功了,但执行时抛了错,得用try/catch包裹模块导出的函数调用 - HTTP 错误(如 500)会被 reject,但浏览器可能缓存了失败响应,导致后续 import() 一直失败却不重试 —— 此时需要手动清缓存或加时间戳参数:
import('./mod.js?t=' + Date.now()) - 模块路径拼错、大小写不符(尤其在 Windows 开发 macOS 部署时)、缺少扩展名(
.js)都会导致 404,而错误堆栈里往往只显示Failed to fetch dynamically imported module,没具体 URL —— 建议在 import 前先console.log路径确认
Webpack/Vite 打包后 import() 路径突然 404?
不是路径写错了,是构建工具把文件名哈希化了,而你写的字符串路径没被识别为动态导入依赖,导致没生成对应 chunk,也没更新引用路径。
立即学习“前端免费学习笔记(深入)”;
- Webpack 要求路径必须是“可静态分析”的:允许变量拼接,但不能是完全运行时计算(如
import(base + name + '.js')会失效);推荐用import(`./pages/${page}.js`)这种模板字符串形式,Webpack/Vite 都能自动收集所有匹配文件 - Vite 默认启用
build.rollupOptions.output.manualChunks,但如果你关了或配了自定义分包规则,import()可能被塞进主包,失去“按需”意义 —— 检查 dist 目录下是否真生成了独立xxx.xxxxxx.js文件 - 部署到子路径(如
/app/)时,Vite 需要设base: '/app/',否则 import() 加载的 chunk 路径会从根开始请求,404











