跨浏览器兼容处理
场景
项目需要兼容 Chrome、Firefox、Safari、Edge 等主流浏览器,部分用户甚至还在用旧版浏览器。如何系统性地处理兼容问题?
方案设计
1. 特性检测优于浏览器检测
feature-detection.ts
// ❌ 浏览器检测(不可靠)
if (navigator.userAgent.includes('Chrome')) { ... }
// ✅ 特性检测
if ('IntersectionObserver' in window) {
// 使用 IntersectionObserver
} else {
// 降级方案:scroll 事件 + getBoundingClientRect
}
// ✅ CSS 特性检测
if (CSS.supports('display', 'grid')) {
// 使用 Grid 布局
}
CSS @supports
/* CSS 层面特性检测 */
@supports (backdrop-filter: blur(10px)) {
.header { backdrop-filter: blur(10px); }
}
@supports not (backdrop-filter: blur(10px)) {
.header { background: rgba(255, 255, 255, 0.9); }
}
2. Browserslist + 工具链
package.json 或 .browserslistrc
{
"browserslist": [
"> 1%",
"last 2 versions",
"not dead",
"not ie 11"
]
}
这个配置会自动影响:
- Babel:决定需要转译哪些语法
- PostCSS/Autoprefixer:决定需要加哪些 CSS 前缀
- core-js:决定需要哪些 Polyfill
3. Polyfill 策略
按需 Polyfill(推荐)
// Babel + core-js 按需引入
// babel.config.js
export default {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage', // 按使用自动引入
corejs: 3,
}],
],
};
// 或使用 polyfill.io 动态加载(按浏览器 UA 返回)
// <script src="https://polyfill.io/v3/polyfill.min.js?features=IntersectionObserver,Promise"></script>
4. CSS 兼容速查
| CSS 特性 | 兼容方案 |
|---|---|
| Flexbox | 基本全兼容,注意 Safari 的 gap 支持(15.4+) |
| Grid | IE 不支持,其他主流兼容 |
dvh/svh/lvh | Safari 15.4+,降级用 JS 计算 |
| Container Queries | Chrome 105+,降级用媒体查询 |
:has() | Safari 15.4+,Chrome 105+,Firefox 121+ |
color-mix() | Chrome 111+,Safari 16.2+ |
常见面试问题
Q1: 如何制定项目的浏览器兼容策略?
答案:
- 数据驱动:根据埋点数据分析用户实际浏览器分布,确定支持范围
- 配置 Browserslist:统一影响 Babel/PostCSS/ESLint
- 分级支持:
- A 级(完全支持):最新 2 版本的 Chrome/Firefox/Safari/Edge
- B 级(基本可用):功能正常但体验降级
- C 级(不支持):展示升级提示
Q2: Babel 和 PostCSS 在兼容性中各负责什么?
答案:
| 工具 | 负责范围 | 例子 |
|---|---|---|
| Babel | JS 语法转译 + API Polyfill | ?. → 普通判断 / Promise.allSettled polyfill |
| PostCSS | CSS 语法转换 + 前缀 | display: flex → -webkit-flex |
| TypeScript | 类型擦除 + 语法降级 | enum → 对象 |
它们都读取 Browserslist 配置来决定转换范围。