后台心经: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.sendMessagechrome.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插件开发,手把手教你构建实用功能,开启浏览器扩展创作之旅。

全部评论
蹲蹲公司
点赞 回复 分享
发布于 08-09 20:27 江苏
名字说一下
点赞 回复 分享
发布于 08-09 20:27 江苏
有够实用
点赞 回复 分享
发布于 08-05 23:37 上海
我去好强😁
点赞 回复 分享
发布于 08-05 12:25 江苏

相关推荐

08-07 23:54
门头沟学院 Java
自来熟的放鸽子能手面...:团子转正仁义这一块。/
投递美团等公司10个岗位
点赞 评论 收藏
分享
评论
5
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务