兼容性数据躺在 JSON(常见的数据文本格式)里,像搬家后满屋编织袋:锅碗瓢盆一件没少,可你半夜要找牙刷,还是得跪在地上翻。我判断得很直白:兼容性数据,不进 SQL(数据库查询语言)就不算能用。

这正是 simonw/browser-compat-db 的锋利之处。它没有发明新事实,只是把 mdn/browser-compat-data 那堆树状文件,改造成一份能查、能连、能更新、能追责的数据库。听上去像搬运,实际上是修路:以前你面对的是材料堆,现在你得到的是通车网。

可下载,不等于可用;可浏览,不等于可查询。

反常识就在这儿。兼容性数据最难的,从来不是“有没有”,而是“怎么问”。工程里真正的问题不是“这个特性能不能用”,而是“Safari 16.4 对这个子特性支持到哪一步”“哪些移动浏览器看似支持,其实还得开开关”“2024 年之后发布的版本里,哪些还只是半截工程”。这些都不是文件问题,而是关系问题。

仓库里现在拆出了 17 个浏览器、1599 条版本发布、19834 个特性、260715 条支持记录。更麻烦的是,原始结构一点也不老实:任意层都可能冒出 __compat;同一个 support 字段,有时是单条记录,有时是数组,有时还是 mirror(沿用上游浏览器结果);同一个 version_added 字段里,既可能装着 "57" 这样的版本号,也可能装着 true(支持但版本不明)、false(明确不支持)或空值。项目附带的 notes.md 把这些怪脾气写得很清楚。

JSON 适合寄存事实,SQL 才适合盘问事实。

周五夜里十一点四十,小周在电商结算页里用了 :has()。客户甩来一段 iPhone 录屏:按钮没了。她去翻原始兼容性仓库,不是在查答案,而是在树杈里捉迷藏:先找路径,再看 Safari 那段到底是单对象、数组,还是夹着备注的多段历史。等她把真相翻出来,故障已经从技术问题变成值班制度问题。换成数据库,一句按浏览器、特性、版本筛选的查询,十秒钟就能把夜里的体面捞回来。

周一早上九点二十,测试主管老邓要给项目经理一张表:我们支持的移动浏览器里,哪些特性需要手动开 flag(功能开关),哪些只是部分实现,哪些版本虽然算“当前”,却还不稳。这个问题在原始 JSON 里几乎没有句法。浏览器发布日期在一处,版本状态在一处,特性支持又埋在另一处层层嵌套。你可以说数据都在,但那句话就像说“螺丝、木板、铰链都在,门应该算装好了吧”。

兼容性不是一道判断题,它是版本、血缘、开关和妥协的户口簿。

浏览器世界也并不是什么共和国大会,很多时候更像宗族社会:名字分家了,血缘没分。mirror 这个字段,说的就是这种关系。一个浏览器表面独立,实际沿用上游结果;如果不把这种血缘落成明确字段,你算兼容性就会像清点重名户口,数字看着整齐,祖宗已经串了。browser-compat-db 的高明,不是把复杂性抹掉,而是把复杂性安置到它该待的位置。

周三下午三点十分,一个做内部开发助手的小团队,想给模型接上兼容性查询。老板以为把仓库塞进去,答案就会自己长出来。结果模型把 mirror 当“已支持”,把 true 当版本号,把“部分实现”听成“差不多能上线”。这不是模型嘴笨,是原始数据本来就不是给顺嘴回答准备的。这个项目最关键的一刀,是把版本信息拆成“版本字符串”和 supported(是否支持)两列,把说明、规范链接、开关、父子特性分别入表,再把上游版本和导入时间记下来。数据库不是高级文件夹,它是防止胡说八道的语法课。

一列里同时塞着版本号、是、否、未知,不叫丰富,叫甩锅。

更要命的是,兼容性数据是活的。今天支持,明天撤回;今天还是实验,后天转正。这个库每次重跑,都按稳定主键增删改,并把上游版本和更新时间写进元数据。能刷新,才叫数据;只能截图,还是公告栏。工程世界里,很多人以为自己缺的是更多资料,其实缺的是一套让资料持续可问、可核、可更新的秩序。

我对这件事的判断没有打算拐弯。simonw/browser-compat-db 真正说透的一句话就是:兼容性数据的价值,不在于它被收集得多完整,而在于它能不能被追问、被连接、被更新、被复算。前者只是仓库,后者才是基础设施。

技术圈最爱的一种自欺,是把“我有数据”错听成“我有答案”。其实两者中间隔着主键、外键、索引、更新时间,也隔着对现实复杂性的尊重。兼容性数据,不进 SQL,就还是一屋子编织袋:东西都在,生活还没开始。


别人聊 AI,我们测 AI——每个结论都能下载原始数据自己复算。 🔗 官网 👉 https://crawdpad.com