nomodule不是降级开关而是加载过滤器,必须与type="module"成对使用:现代浏览器跳过nomodule脚本,旧浏览器执行;legacy-bundle.js需真es5兼容并前置polyfill,否则ie11必崩溃。

nomodule不是降级开关,是加载过滤器
单独写 <script nomodule src="legacy.js"></script> 会导致新旧浏览器都白屏:Chrome/Firefox/Safari 直接跳过不下载,IE11/Android 4.4 WebView 则静默忽略整行标签(不报错、不执行),脚本彻底丢失。它不是“给旧浏览器用的”,而是“让现代浏览器跳过”的指令,必须和 type="module" 成对出现才构成有效分流。
必须成对使用 module + nomodule
正确结构只有这一种可靠模式:
<script type="module" src="app.mjs"></script><script nomodule src="legacy-bundle.js"></script>
-
app.mjs必须是合法 ES 模块:含import/export,不能有document.write,默认defer -
legacy-bundle.js必须是独立输出的 IIFE 或 UMD 格式,严禁含import/export和dynamic import() - 顺序无关,但推荐模块在前——符合直觉,也方便构建工具识别入口
- Safari 10.1 是唯一例外:会同时执行两者,需加运行时检测规避重复初始化
legacy-bundle.js 必须真·ES5 兼容
nomodule 只管“要不要加载”,不管“能不能跑”。哪怕脚本进了 IE11,以下任一情况都会立刻崩溃:
- 语法层面:含
const、let、=>、${}、class→ 直接SyntaxError - API 层面:调用
fetch()、Promise、Array.from()、Object.assign()→ReferenceError或静默失败 - DOM 层面:
element.classList.add()(IE9–)、querySelector()(IE7–)、addEventListener()(IE8–)→ 报错或无响应
构建时必须显式设 targets: { ie: "11" },手动引入 core-js/stable,且 polyfill 必须在所有业务代码之前执行。
验证是否生效,别看控制台,看网络请求
最可靠的验证方式不是 console.log,而是检查实际行为:
- Chrome DevTools Network 面板过滤
legacy-bundle.js—— 它不该出现在请求列表里(说明被现代浏览器跳过) - IE11 控制台执行
typeof module应返回"undefined",且确认legacy-bundle.js中的初始化逻辑已执行(比如全局变量已挂载、DOM 已修改) - 禁用 JS 后测试
<noscript></noscript>内容是否可见——它和nomodule无关,只响应 JS 引擎关闭,不兜底加载失败
真正容易被忽略的是:legacy 脚本里任何一处未 polyfill 的 API 调用,都会让整个页面在 IE11 里卡死;而现代浏览器根本不会帮你加载它,所以问题只会在旧环境暴露,且难以复现。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











