应使用 import() 动态导入替代 script 标签或 innerHTML 注入 ESM 模块,因其能正确触发模块加载机制、支持路径变量与错误处理,并配合 DOMParser 安全注入 HTML 结构。

在动态脚本注入场景中,直接用 <script> 标签插入 ESM 模块会失败——浏览器不执行其中的 import 语句,也不识别 type="module" 属性(除非显式设置)。真正的模块加载必须走标准 ESM 加载机制,不能靠字符串拼接或 innerHTML 触发。核心解法是:**避开 DOM 注入脚本的陷阱,改用 import() 动态导入 + 手动挂载逻辑**。
为什么不能用 innerHTML 或 script 标签注入 ESM
动态插入含 <script type="module"> 的 HTML 片段时:
- 浏览器不会解析其中的
import语句,报错Cannot use import statement outside a module -
type="module"属性仅在初始 HTML 解析阶段生效,动态插入的 script 不触发模块加载流程 - 即使手动创建
document.createElement('script')并设type="module",若 src 是相对路径且无正确 base URL,仍会 404 或 CORS
正确方式:用 import() 替代脚本注入
把“加载模块”和“执行逻辑”分离。不注入脚本字符串,而是运行时调用 import() 获取模块对象,再调用其导出函数:
- 适用于按钮点击、路由跳转、条件弹窗等按需场景
- 路径可为变量或模板字符串:
import(`./features/${featureName}.js`) - 返回 Promise,支持
await或.then(),错误可捕获
示例:点击后加载并初始化一个组件模块
立即学习“Java免费学习笔记(深入)”;
async function loadComponent() {try {
const { default: MyComponent } = await import('./components/MyComponent.js');
MyComponent.init(document.getElementById('target'));
} catch (err) {
console.error('模块加载失败', err);
}
}
配合 DOMParser 安全注入 HTML 结构(不含脚本)
若动态内容包含 HTML 模板(如模态框结构),应只注入纯 HTML,不带 <script>:
- 用
DOMParser解析字符串,提取元素节点 - 将结构插入 DOM 后,再通过
import()加载对应模块并绑定行为 - 避免
innerHTML执行任意脚本,提升安全性
这样既保持结构动态性,又守住模块加载的规范路径。
注意开发与部署环境差异
ESM 动态导入依赖运行环境支持:
- 本地测试需 HTTP 服务(如 Live Server),不能用
file://协议(CORS 阻止模块加载) - 路径必须符合模块解析规则:相对路径以
./或../开头;裸名(如react)需构建工具配置别名或通过 CDN 导入 - 生产环境建议搭配代码分割(如 Vite / Webpack 的
import()自动分包),减少首屏体积


















