兼容清单与常见坑
本教程共 56 篇 · 第 53 篇 · 更新于 2026-08-13 · 约 6 分钟阅读
本节目标:学完你能拿着一份 Chrome↔Firefox 差异清单自查,知道 Safari 哪些 API 受限,并掌握”先查兼容表、再做特性检测、最后分浏览器调试”的排查套路。
前面两节解决了”写法统一”。但扩展要在多家浏览器跑通,还有第二关:能力差异。有的 API 这家有、那家没有;有的方法参数这家多、那家少。这一节把常见差异、Safari 的限制和排查思路一次讲清。
53-1 Chrome 与 Firefox 差异清单
先给一张高频差异表,写代码时对照自查:
| 维度 | Chrome / Edge | Firefox |
|---|---|---|
| API 命名空间 | chrome.* | browser.*(也兼容 chrome.*) |
| 异步风格 | 回调为主,Chrome 121+ 支持 Promise | Promise 化 |
| 后台模型 | background.service_worker,事件驱动 | background.service_worker,事件驱动(细节略有差异) |
| 专属清单字段 | 无 | browser_specific_settings.gecko.id |
| 侧边栏 | side_panel | sidebar_action(两者互不兼容) |
| 部分 API 覆盖 | 广 | 个别方法不支持或行为不同 |
需要更新的认知:从 Chrome 148 起,Chromium 也原生提供了 browser 命名空间(Chrome 152 起覆盖全部扩展场景,含 devtools),“Chrome 只有 chrome.*”的说法已不再成立。Mozilla 的 webextension-polyfill 也已宣布冻结、不再更新。polyfill 现在的定位是兼容旧版 Chrome 与统一写法的过渡方案,新项目可以评估直接用原生 browser.*。
实际开发里,差异大多落在”某个方法在 Firefox 上不支持”或”参数含义微调”。例如通知 API 的部分回调事件、某些标签页方法。这些细节上,Firefox 与 Chrome 并非百分百对齐。权威做法是查 MDN 的 “Browser support for JavaScript APIs” 兼容表,每个 API 页都带各浏览器支持标记。
// 不要假设某方法家家都有,发布前查 MDN 兼容表
// 例如 storage、tabs、scripting 各方法的 Firefox/Chrome 标记
Note一个实用经验:先以 Chrome(MV3 主线)写完功能,再在 Firefox 用
about:debugging加载临时扩展跑一遍。报错的 API 就是差异点,比纯靠记忆更可靠。
53-2 Safari 的受限 API
Safari 也实现 WebExtensions,但它是”子集”实现,限制最多。关键点先说清:Safari 同时支持 chrome.* 和 browser.* 两种命名空间,也同时支持回调和 Promise。正因如此,它和 polyfill 相处得不错。但能力覆盖是短板。
常见限制(以当前 Safari 版本为准,发布前再核对 MDN):
storage.sync:本地存储机制可用,但跨设备同步不支持。identity:不支持,OAuth 登录要改在新标签页里做。runtime.setUninstallURL/runtime.onUpdateAvailable:不支持。permissions.webRequestBlocking:不支持;webRequest在 iOS 上也不支持阻塞。devtools:较新 Safari(16+)才支持。scripting.executeScript的injectImmediately等参数不支持。cookies.onChanged等部分事件不支持。update_url:不支持,Safari 扩展更新走 App Store。
另外,Safari 会忽略清单里不支持的字段,不会报错。这既是好事(不会崩),也是坑:你以为配了,却没生效。Safari 还忽略 manifest 权限里的 file:// 协议,用到要自己兜底。
{
"browser_specific_settings": {
"safari": {
"strict_min_version": "16.0"
}
}
}
TipSafari 扩展最终要包进一个 App、走 App Store 上架,不能直接传 zip 到商店。它的分发链路和 Chrome Web Store / Firefox Add-ons 完全不同,规划时就得算进去。
另外,iOS 上的 Safari 限制比 macOS 更多。比如 windows 的部分创建与关闭方法、tabs.move、上下文菜单,在 iOS 上都不支持。如果你的扩展要覆盖 iPhone 和 iPad,得额外按 iOS 的兼容表再查一遍。不能只看 macOS 版 Safari 的支持情况,否则上线后才发现移动端功能缺失。
53-3 用特性检测兜底
能力缺失不能靠 polyfill 变出来,得在代码里自己判断。思路是:用之前先确认这个 API 或方法在运行时存在。
// 特性检测:方法不存在就走降级
async function saveSync(key, value) {
if (browser.storage.sync) {
try {
await browser.storage.sync.set({ [key]: value });
return;
} catch (err) {
console.warn("sync 失败,回退 local", err);
}
}
// Safari 等不支持 sync 的环境走 local
await browser.storage.local.set({ [key]: value });
}
这种”先试主路径、失败回退”的写法,能让一份代码在能力不同的浏览器上都优雅降级。它不会直接抛错崩溃。
// 检测某个 API 是否存在
if (typeof browser.identity !== "undefined") {
// 走 identity 登录
} else {
// 走新标签页 OAuth
}
53-4 各浏览器调试入口
排查跨浏览器问题,得知道去哪看:
- Chrome / Edge:
chrome://extensions开开发者模式,Load Unpacked 加载,点服务工作者(Service Worker)链接看后台日志。 - Firefox:访问
about:debugging#/runtime/this-firefox,点”临时载入附加组件”,选 manifest.json,即可加载并查看控制台。 - Safari:先在”开发”菜单开启”允许未签名扩展”。扩展跑在 Safari 里,用 Web 检查器看日志。
Note同一份代码,在 Firefox 用
about:debugging跑一遍,在 Chrome 用chrome://extensions跑一遍。两边都能跑通,才叫真跨浏览器。只在一家居然不算。
53-5 一套排查套路
把前面的串成流程。这套流程不必一次全做。先查兼容表、再分浏览器实测,已经能挡掉绝大多数跨浏览器问题。等真遇到缺失能力,再回头补特性检测。
- 写之前查兼容表:MDN “Browser support for JavaScript APIs” 标了每个 API 在各浏览器的支持情况,先避坑。
- 统一写法:全项目
browser.*+ polyfill,别混chrome.*。 - 特性检测兜底:对可能缺失的 API 做存在性判断和降级。
- 分浏览器实测:Firefox 用
about:debugging、Chrome 用开发者模式、Safari 用 Web 检查器,逐个加载验证。 - 清单分变体:用构建脚本产出带
browser_specific_settings的各家清单。
// 排查时的通用日志模板
try {
const res = await browser.tabs.query({ active: true });
console.log("当前标签", res);
} catch (err) {
console.error("该浏览器可能不支持此用法", err);
}
53-6 Edge 几乎等同 Chrome
提跨浏览器,常被人忽略的是 Edge。Edge 基于 Chromium 内核,扩展 API 与 Chrome 几乎完全一致:命名空间是 chrome.*、异步风格相同、清单字段相同。所以只要你按 Chrome(MV3 主线)写、再用 polyfill 兼容 Firefox,Edge 基本”免费”就能跑。
真正不同的是分发链路:Edge 走 Edge Add-ons 商店,审核节奏和 Chrome Web Store 不同,但代码不用改动。一个实用提醒是:商店托管(Chrome Web Store / Edge Add-ons)的扩展会自动更新,清单里不需要配 update_url。只有自托管分发才需要声明它(见第 50 章),构建清单分变体时基本不用操心这个字段。
| 浏览器 | 内核 | 命名空间 | 分发渠道 |
|---|---|---|---|
| Chrome | Chromium | chrome.* | Chrome Web Store |
| Edge | Chromium | chrome.* | Edge Add-ons |
| Firefox | Gecko | browser.* | Firefox Add-ons |
| Safari | WebKit | 两者都支持 | App Store |
Tip跨浏览器工程的优先级建议:先打通 Chrome + Edge(几乎零成本),再用 polyfill 接 Firefox,最后按需兼容 Safari 的子集能力。这样投入产出比最高。
53-7 小结
跨浏览器三件事:
- 写法统一靠 polyfill,命名空间和异步风格不再是障碍。
- 能力差异靠清单自查 + 特性检测,缺失就降级。
- Safari 最受限、Edge 最接近 Chrome:Safari 是子集实现、走 App Store;Edge 等同 Chrome,基本免费兼容。
到这,模块十二的跨浏览器兼容就讲完了。你已经有了一套代码跑 Chrome、Firefox、Edge 的思路,Safari 也能按需兼容。下一模块我们转向现代构建工具链,看怎么用 Vite 把这套跨浏览器工程真正跑顺。