html5shiv必须在ie条件注释中置于head内、css前加载,并配合display:block声明;webshim需按需加载forms等模块;polyfill须内联轻量级、注意执行顺序与依赖关系;custom elements在ie中不可polyfill,需降级处理;语法降级与api补丁须同步进行。

html5shiv 加载时机和位置错不得
IE8 及以下浏览器遇到 <header></header>、<section></section> 这类标签,根本不会创建 DOM 节点——不是样式不生效,是压根没这个元素。所以 html5shiv 必须在 里、任何 CSS 引入之前执行,且只能对 IE 条件注释启用:
<!--[if lt IE 9]> <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js"></script> <![endif]-->
漏掉条件注释,现代浏览器也会加载它;放在 CSS 后面,即使 DOM 创建了,样式也命中不了那些标签。另外,光有 html5shiv 不够,CSS 中必须显式声明:header, section, article, aside, nav, footer { display: block; },因为 IE 默认把未知标签当 inline 元素处理。
webshim 加载 forms 模块时别贪全
required、placeholder 这些表单属性在 IE9 以下连 DOM 属性都不会挂载,html5shiv 对它们完全无效。用 webshim 是更进一步的方案,但要注意按需加载:
- 只加载真正需要的模块,比如仅表单验证就用
webshims.polyfill('forms'),别调用webshims.polyfill('all') -
placeholder补丁要监听focus/blur,动态插入/移除文本节点,不能污染input.value - 不要试图用
::placeholder伪类“修复” IE8 的 placeholder —— 它根本不支持该伪元素
polyfill 脚本体积和执行顺序直接影响首屏
很多项目把所有 polyfill 打包进一个 vendor.js,结果 IE8 首屏 JS 解析时间暴涨。关键不是“要不要加”,而是“谁先跑、跑多少”:
- 内联轻量 polyfill(如
globalThis、Object.entries)比外链更安全:避免额外请求阻塞,且能确保在任何业务代码前执行 - 像
fetch这种依赖Promise的 API,必须先确认window.Promise存在,再加载whatwg-fetch,否则直接报错 - 多个 polyfill 之间可能冲突:比如同时引入
es6-promise和core-js/stable/promise,会导致Promise被重复定义,部分方法行为异常
Custom Elements 在 IE 中根本不可 polyfill
customElements.define() 这类 Web Components API 在 IE 中没有可靠 polyfill。哪怕你用了 @webcomponents/webcomponentsjs,也只是让 Chrome 33+ 等旧版现代浏览器能用,对 IE 完全无效。这时候必须降级处理:
- 用 class 名 + data-* 属性模拟组件行为,比如
<div class="tabs" data-tabs>,再配 JS 初始化<li>避免在 IE 环境中渲染依赖 <code>customElements的组件树,否则会卡在document.createElement('my-button')报错 - 如果必须用 Web Components,就得接受 IE 用户看到的是静态 HTML 或服务端降级内容
最常被忽略的点是:polyfill 不解决语法问题。哪怕你加了 core-js,如果源码里写了箭头函数或 async/await,IE 会在解析第一行就抛 SyntaxError,根本跑不到 polyfill 执行那步。语法降级和 API 补丁得同步做。











