Night Safari:从一个日常需求做出 Safari 扩展

这次做 Night Safari,起点是一个很日常的需求:我想在 Safari 里更舒服地阅读网页。
有的网站已经支持深色模式,有的网站还没有。也有一些网站,正文已经变暗,导航栏或弹出的卡片却仍然很亮。要把这些不同情况放进一个扩展里处理,实际比“把背景改黑”复杂不少。
我希望保留网站原本做得好的主题,在需要时再进行转换,同时提供全局和单个网站的控制。这就是 Night Safari 逐渐形成的方向。

先决定怎样对待网站原来的主题

网站自己设计的深色主题,往往已经考虑了按钮、边框、图片和文字的搭配。如果它可靠地工作,我希望优先使用它。
因此,Night 的自动模式需要先判断:页面有没有可用的原生深色主题,是否能够开启,现在显示的是什么状态。
如果找不到可靠的原生主题,再启用转换引擎。用户也可以针对某个网站选择保留网站主题、强制转换,或者关闭 Night。
读取用户设置与明暗偏好 ↓ 判断网站原生主题 ↙ ↘ 可以使用原生深色 需要进行转换 ↓ ↓ 保留主题、补齐遗漏 启用 Dark Reader
这里的判断无法只看某一块颜色。深色页眉下面可能是浅色正文,一张黑色图片也不能证明整个网站进入了深色模式。

接入 Dark Reader 之后,职责更清楚了

项目迭代到 0.2.0 时,我接入了本地打包的 Dark Reader 动态主题引擎。
Night 继续负责 Safari 的使用体验、主题策略、开关和原生深色处理,Dark Reader 负责没有可用原生主题时的页面转换。
Dark Reader 的动态主题会分析网页颜色与背景,进行相应调整,并尽量保留照片的颜色。这为转换提供了比整页反色更细致的基础。Dark Reader 动态主题介绍
接入成熟引擎之后,我仍然需要处理网站如何判断、引擎什么时候启停,以及停用后怎样恢复。把一个组件接进来,并没有消除产品自己的问题。
同时,本地嵌入的 API 引擎没有自动附带完整扩展的网站修正规则库,实际兼容性仍需要逐个场景验证。

最有代表性的坑:一会黑,一会白

开发过程中,知乎页面出现过主题反复变化的情况。导航栏和通知区域也是需要单独处理的部分。
页面自身会改变样式,Night 会观察变化,转换引擎又会写入新的样式。如果观察器把扩展自己产生的变化再次当作网站更新,就可能反复触发判断。
这让我开始注意一个问题:观察到变化之后,先要弄清楚变化来自哪里。
项目后来对引擎生成的样式、相关加载事件和内部变量进行过滤,减少自己触发自己的反馈。普通局部内容变化交给引擎处理;根主题、网站样式表或策略变化,才重新判断主题。
重复检查时,也尽量复用已有状态和样式,避免不断删除、插入样式表。

原生深色也可能需要补齐

有的网站已经有深色主题,但仍留下少量浅色背景。我不想因为这些局部遗漏,把整页重新转换一遍。
所以项目加入了原生深色补齐:在确认原生主题后,检查可见区域里遗漏的高亮、中性纯色背景,同时修正对比度不足的文字。
图片、视频、SVG、背景图和渐变没有纳入这类补齐。关闭 Night 或恢复浅色时,补齐样式也要移除。
这种通用判断仍有局限。网站有意保留的白色区域可能被改变,复杂背景、伪元素和其他特殊内容也需要额外检查。
对于主题重新判断和颜色复查,项目还处理了 CSS 过渡,减少中间状态被显示出来的机会。

怎样知道这一版真的变好了

2026 年 10 月 5 日的验证记录里,Node 单元测试有十四项通过,本地 Chrome 网页回归覆盖了浅色转换、原生主题切换、动态内容和停用恢复等场景。
这些测试能发现不少问题,但 Chrome 回归使用了部分扩展接口的替身,不能代表真实 Safari 的权限、弹窗消息和注入行为都正确。
我也在 Safari 中加载了扩展,检查演示页与实际网站。知乎主页的导航栏、咨询卡片和悬浮按钮补齐有实际检查记录;通知弹层的一次连续六百帧采样中,被观察的区域保持了深色状态。
这只能说明当时检查到的场景。通知分类切换、滚动,以及长时间运行的性能,仍然需要补测。
这种记录方式让我更容易判断下一步做什么:已经检查过的范围写清楚,没有检查的就继续留下来。

做自己的工具,也要把来源留下来

项目里保留了 Dark Reader 的版权与许可证,并记录了引擎版本、源码 revision 和文件摘要,打包时检查 manifest 引用和 ZIP 完整性。
这些工作有助于以后回答:这一版到底带了哪个引擎,更新时改了什么,别人拿到的包是否完整。
Dark Reader 采用 MIT 许可证,复用时需要保留相应版权与许可文本。具体条款可以直接查看上游许可证。Dark Reader 许可证

接下来,我想继续用它发现问题

目前 Night Safari 仍然是接入原型。跨域资源、复杂动态样式、特殊网站和长期性能,都还有继续完善的空间。
这个项目让我感受到,开发一个日常工具,会把很多细小的问题摆到眼前:打开网页时有没有闪一下,停用后能否恢复,网站自己更新时会不会被干扰。
我想继续围绕这些具体的使用场景改进它。每天会用到的小工具,也可以成为一个认真学习工程细节的机会。
项目:Night Safari
对于本文内容有任何疑问, 可与我联系.