nomodule单独使用会导致新旧浏览器均白屏;它仅在支持type="module"的现代浏览器中作为“跳过指令”生效,ie11等旧浏览器因不识别该属性而静默忽略整行script标签,必须与type="module"成对使用且legacy脚本需es5兼容并含polyfill。

nomodule 单独写在 IE 里根本不会执行
直接写 <script nomodule src="legacy.js"></script>,IE11 会静默忽略整行标签——不报错、不发请求、不执行。这不是 bug,是规范行为:浏览器遇到无法识别的属性(如 nomodule)且无 type 值时,直接跳过该 <script></script> 元素解析。结果就是现代浏览器跳过,旧浏览器也跳过,JS 彻底断掉。
必须和 type="module" 成对出现才有效
IE 识别不了 type="module",所以会跳过那一行;但它能执行普通 <script></script> 标签,前提是没被 nomodule 阻断。正确结构只有这一种组合:
<script type="module" src="app.mjs"></script><script nomodule src="legacy-bundle.js"></script>
- Chrome/Firefox/Safari:加载并执行
app.mjs,完全不下载legacy-bundle.js - IE11/Edge 12–18:跳过第一行(不认识
type="module"),加载并执行第二行(不认识nomodule,但会照常处理src) - Safari 10.1 是特例:两个都执行,需加运行时检测规避重复初始化
legacy-bundle.js 必须是真·ES5 + polyfill
nomodule 只管“要不要加载”,不管“能不能跑”。哪怕脚本进了 IE11,以下任一情况都会立刻崩溃:
- 语法层面:
const、let、=>、${}、class→ 直接SyntaxError - API 层面:
fetch()、Promise、Array.from()、Object.assign()→ReferenceError或静默失败 - DOM 层面:
element.classList.add()(IE9–)、querySelector()(IE7–)、addEventListener()(IE8–)→ 报错或无响应
实操要点:
- Babel 构建目标必须显式设为
targets: { ie: "11" },不能依赖 preset 默认值 -
core-js/stable要手动引入,且 polyfill 必须在所有业务代码之前执行 - 输出格式只能是 IIFE 或 UMD,严禁含
import/export,禁用dynamic import() - Webpack/Vite 需确认
build.target和实际覆盖范围一致,避免残留现代语法
验证是否生效别看控制台,看网络请求
最可靠的验证方式不是查 console,而是观察实际加载行为:
- Chrome DevTools Network 面板过滤
legacy-bundle.js:刷新页面后它不该出现(说明被现代浏览器跳过) - IE11 控制台执行
typeof module应返回"undefined",同时确认legacy-bundle.js中的代码确实运行了(比如打个alert或改document.title) - 若 IE11 里
legacy-bundle.js没执行,优先检查是否漏写了type="module"脚本,或legacy-bundle.js文件路径 404
真正容易被忽略的是:即使 nomodule 加载成功,IE11 的 DOM API 限制和 polyfill 加载时机仍可能导致脚本中途卡死——它不报错,只是静默失效。务必在真实 IE11 环境中测试关键交互路径,而不是只看 JS 是否进入。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











