Highlight
Safari 15 为 Web Extensions 带来了三项关键改进:非持久化后台页面(non-persistent background pages)减少内存占用,declarativeNetRequest API 实现高性能内容拦截,以及新标签页自定义能力。iOS 和 iPadOS 首次支持 Web Extensions。
核心内容
浏览器扩展开发者长期面临一个性能问题:后台页面一旦开启就永远运行,即使用户几小时不用这个扩展,它仍在消耗内存和 CPU。
Safari 15 通过非持久化后台页面解决了这个问题。后台页面只在需要时加载,处理完事件后自动卸载。这对 iOS 设备尤其重要——资源受限的移动设备无法承受多个常驻后台进程。
非持久化后台页面
传统扩展的后台页面是持久的:
{
"background": {
"scripts": ["background.js"]
}
}
这会导致后台进程永远运行。改为非持久化:
{
"background": {
"scripts": ["background.js"],
"persistent": false
}
}
(03:22)
关键点:
- 事件监听器必须在脚本顶层注册,不能在回调内部注册
- 用
browser.storageAPI 代替全局变量保存状态 - 移除
webRequest监听器,它的事件频率太高,与非持久化页面不兼容 - 用
browser.alarms代替setTimeout/setInterval
使用 storage API 保存状态
// background.js
// 错误:全局变量会在页面卸载后丢失
let replacementCount = 0;
// 正确:使用 storage API
let replacementCount = 0;
browser.storage.local.get('count').then(result => {
replacementCount = result.count || 0;
});
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'replace') {
replacementCount += message.count;
browser.storage.local.set({ count: replacementCount });
} else if (message.action === 'getCount') {
sendResponse({ count: replacementCount });
}
});
(06:55)
关键点:
browser.storage.local是异步 API,数据持久化到磁盘- 需要在 manifest 中添加
storage权限 - 事件监听器注册在
storage.get()的回调外面,确保页面加载时就注册好
declarativeNetRequest 内容拦截
这是 Chrome 引入的 API,Safari 15 开始支持。规则以 JSON 格式声明,浏览器在底层匹配,扩展不需要运行 JavaScript 就能看到请求内容。
manifest.json:
{
"permissions": ["declarativeNetRequest"],
"declarative_net_request": {
"rule_resources": [
{
"id": "ruleset_1",
"enabled": true,
"path": "rules.json"
}
]
}
}
(08:37)
rules.json:
[
{
"id": 1,
"priority": 1,
"action": {
"type": "block"
},
"condition": {
"regexFilter": ".*\\.(jpg|png|gif)$",
"resourceTypes": ["image"]
}
},
{
"id": 2,
"priority": 2,
"action": {
"type": "allow"
},
"condition": {
"urlFilter": "||wikipedia.org",
"resourceTypes": ["image"]
}
}
]
(09:49)
关键点:
priority决定规则应用顺序,数值大的优先action.type可以是block、allow或upgradeSchemeresourceTypes包括main_frame、script、image、stylesheet等domainType可区分 first-party 和 third-party 请求- 扩展不需要
webRequest权限即可拦截内容,隐私性更好
自定义新标签页
扩展可以接管 Safari 的新标签页:
{
"chrome_url_overrides": {
"newtab": "newtab.html"
}
}
(13:34)
newtab.html:
<!DOCTYPE html>
<html>
<head>
<title>My New Tab</title>
<meta name="theme-color" content="#ff6b6b">
</head>
<body>
<h1>Welcome!</h1>
<p>Fun fact of the day...</p>
</body>
</html>
用户开启扩展时,Safari 会询问是否允许扩展接管新标签页。可以在 Safari 设置中随时更改这个选择。
详细内容
调试非持久化后台页面
Safari 的 Develop 菜单中新增了 “Web Extension Background Pages” 选项,可以查看后台页面的加载状态。
// 检查后台页面是否已加载
browser.runtime.getBackgroundPage().then(page => {
if (page) {
console.log("Background page is active");
} else {
console.log("Background page is unloaded");
}
});
关键点:
getBackgroundPage()在页面已卸载时返回 null,不会自动唤醒页面- 要唤醒后台页面,发送一条消息即可
- 在 Develop 菜单中点击后台页面会立即加载它
iOS 上的特殊注意事项
iOS 扩展必须使用非持久化后台页面。manifest 中如果省略 persistent 字段,默认就是 true,在 iOS 上会导致扩展无法加载。
{
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": ["storage", "declarativeNetRequest"]
}
规则集动态更新
// 启用或禁用特定规则集
browser.declarativeNetRequest.updateEnabledRulesets({
disableRulesetIds: ['ruleset_1'],
enableRulesetIds: ['ruleset_2']
});
// 获取当前规则集状态
browser.declarativeNetRequest.getEnabledRulesets().then(ids => {
console.log("Enabled rulesets:", ids);
});
核心启发
1. 为 iOS 开发广告/内容拦截扩展
用 declarativeNetRequest API 构建轻量级拦截器,规则文件可以远程更新,无需提交 App Store 审核。入口 API:declarativeNetRequest + updateEnabledRulesets()。
2. 创建跨平台的密码管理器扩展
用非持久化后台页面 + storage API 保存用户凭证,通过 content script 在网页表单中自动填充。入口 API:browser.storage.local + content_scripts。
3. 开发 productivity 类新标签页扩展
接管 Safari 新标签页,展示待办事项、天气或每日一句。用 theme-color meta 标签让标签栏颜色与扩展风格统一。入口 API:chrome_url_overrides + newtab。
4. 构建开发者工具扩展
在网页上注入 content script,展示元素的布局信息、颜色值或性能数据。用 browser.runtime.sendMessage 与后台页面通信聚合数据。入口 API:content_scripts + browser.runtime.onMessage。
5. 实现网页暗黑模式强制切换
用 content script 检测网页当前主题,通过 declarativeNetRequest 拦截并修改 CSS 文件请求,或直接用 JavaScript 注入反转颜色的样式。入口 API:content_scripts + CSS 注入。
关联 Session
- Meet Safari Web Extensions on iOS — iOS 上构建和发布 Safari 扩展的完整指南
- Design for Safari 15 — Safari 15 的视觉设计和 theme-color 使用
- What’s new in Web Inspector — 调试 Web Extension 的新工具
评论
GitHub Issues · utterances