后台心经:Service Worker 的值守与事件响应
在谷歌浏览器插件开发中,Service Worker是一个由浏览器在后台独立运行的事件驱动脚本(background script,替代Manifest V2 中的后台页面),通常在扩展的manifest.json中以“background”字段指定。其核心作用是通过注册事件监听器响应浏览器事件,该脚本的生命周期由浏览器完全控制,在事件触发时激活,空闲时自动终止。
用通俗的话来说,Server Worker就像浏览器大楼的智能值班员。 平时在后台值班室“睡觉”(不占资源),但给整栋楼装了呼叫铃(事件监听)。一旦有事发生(如定时闹钟响、前台发消息、用户开新页面),它立刻“醒”来处理。活干完30秒没新事,它又自动“睡”了。 它不碰用户房间(无DOM权限),重要事都记值班日志(Storage API),只为高效响应、绝不赖着不走。
核心职责---事件响应中心
Service Worker 的核心功能之一,是作为插件的“事件响应中心”,负责监听并处理各种浏览器事件。常见的事件包括:
chrome.runtime.onInstalled
:扩展安装或更新时触发chrome.alarms.onAlarm
:定时任务触发chrome.tabs.onUpdated
:标签页内容更新时触发chrome.runtime.onMessage
:接收到消息时触发chrome.action.onClicked
:用户点击扩展图标时触发
通过为这些事件注册监听器,Service Worker 可以灵活地响应用户的操作或系统的状态变化,成为插件功能实现的关键枢纽。
沟通桥梁---协调扩展组件
除了事件响应,Service Worker 还承担着协调插件中各个组件之间通信的职责。一个典型的 Chrome 插件通常由多个部分组成,例如:
- Popup 页面:用户点击图标时弹出的界面
- Content Script:注入到网页中的脚本,用于操作页面内容
- Service Worker:后台逻辑处理核心
这些组件之间往往需要进行数据交换或行为协调。而 Service Worker 正是这些组件之间的“通信中枢”,通过 chrome.runtime.sendMessage
和 chrome.runtime.onMessage
等 API 实现高效、安全的消息传递。
光说不练花架子,我们再来看两个案例,简单实践一下!
实践案例 --- 合并窗口
有些时候,我们会打开多个浏览器窗口,不同的窗口上分布着不同的标签,切来切去怪麻烦的,这时候,我们就可以做一个插件,当点击插件的图标时,自动将所有窗口合并。
目录结构
{ "manifest_version": 3, "name": "窗口合并", "version": "1.0", "description": "合并多个浏览器窗口的标签到当前激活的浏览器窗口", "permissions": [ "tabs" ], "icons": { "16": "assets/icon.png", "32": "assets/icon.png" }, "action": { "default_icon": { "16": "assets/icon.png", "32": "assets/icon.png" }, "default_title": "合并窗口工具" }, "background": { "service_worker": "background.js" } }
//当点击扩展程序图标时触发 chrome.action.onClicked.addListener(async() =>{ try { //获取所有浏览器窗口,populate参数表示获取窗口并且包含标签页信息 const allWindows = await chrome.windows.getAll({ populate: true }); //获取当前激活窗口 const currentWindow = await chrome.windows.getCurrent(); //收集其他窗口的标签页 const tabsToMove = []; const windowsToClose = []; for(const win of allWindows){ if (win.id !== currentWindow.id) { win.tabs.forEach(tab => tabsToMove.push(tab.id)); windowsToClose.push(win.id); } } //合并标签页到当前窗口 if(tabsToMove.length > 0){ //获取当前窗口最后一个标签页位置 const currentTabs = await chrome.tabs.query({ windowId: currentWindow.id }); const lastIndex = currentTabs.length > 0 ? currentTabs[currentTabs.length - 1].index + 1 : 0; // 移动标签页到当前窗口尾部 await chrome.tabs.move(tabsToMove, { windowId: currentWindow.id, index: lastIndex }); } //关闭其余窗口 for (const winId of windowsToClose) { await chrome.windows.remove(winId); } } catch (error) { console.error('合并窗口失败') } })
成果展示
实践案例 --- 定时护眼助手
当我们专注工作时,常常一盯屏幕就是好久,不自觉就忘了休息。这对眼睛可不太友好。,可不可以让浏览器自动提醒我们护眼呢,当然是可以的!
目录结构
{ "manifest_version": 3, "name": "定时护眼助手", "version": "1.0", "description": "每30分钟提醒护眼的简单插件", "icons": { "16": "/assests/icon16.png", "32": "/assests/icon32.png" }, "permissions": [ "alarms", "activeTab", "scripting" ], "background": { "service_worker": "background.js" }, "action": { "default_icon": "/assests/icon16.png" } }
// 安装时创建定时任务 chrome.runtime.onInstalled.addListener(() => { // 创建30分钟循环定时器 chrome.alarms.create("eyeCareReminder", { delayInMinutes: 30, // 首次触发时间(测试可用0.1分钟) periodInMinutes: 30 // 循环间隔 }); }); // 监听定时事件 chrome.alarms.onAlarm.addListener((alarm) => { if (alarm.name === "eyeCareReminder") { // 获取当前激活的标签页 chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { if (tabs[0]?.id) { // 注入提醒脚本 chrome.scripting.executeScript({ target: { tabId: tabs[0].id }, func: showReminder }); } }); } }); // 通过函数字符串注入代码(注意作用域限制) function showReminder() { // 避免重复插入 if (document.getElementById("eye-care-reminder")) return; const style = ` #eye-care-reminder { position: fixed; top: 0; left: 0; width: 100%; background: #ffd700; color: #000; text-align: center; padding: 8px 0; font-family: sans-serif; z-index: 99999; box-shadow: 0 2px 4px rgba(0,0,0,0.2); } #eye-care-close { margin-left: 10px; background: #ff4d4d; border: none; padding: 2px 6px; cursor: pointer; border-radius: 3px; } `; const markup = ` <style>${style}</style> <div id="eye-care-reminder"> 🌿 该休息眼睛啦!请眺望远处20秒 <button id="eye-care-close">✖</button> </div> `; // 插入提醒元素 document.body.insertAdjacentHTML("afterbegin", markup); // 添加关闭功能 document.getElementById("eye-care-close")?.addEventListener("click", () => { document.getElementById("eye-care-reminder")?.remove(); }); }
成果展示
从零探索Chrome插件开发,手把手教你构建实用功能,开启浏览器扩展创作之旅。