Chrome插件开发:Service Worker、Content Scripts和插件内部网页工作流程

2,796 阅读6分钟

Chrome插件开发:Service Worker、Content Scripts和插件内部网页工作流程

Chrome插件的核心组件包括Service Worker、Content Scripts和插件内部网页(Popup),它们各自具有不同的工作流程和功能。本文将详细介绍这些组件之间的协作以及它们的用途。

1. Service Worker

Service Worker是Chrome插件的后台脚本,其主要任务是拦截和处理网络请求,以及管理缓存。以下是Service Worker的工作流程:

  • 安装(Installation):Service Worker在首次注册时触发安装事件。在此事件中,通常会缓存所需的资源,以便在离线时可以访问。这一步骤对于提供离线支持至关重要。

  • 激活(Activation):激活事件在Service Worker安装后触发。在这个阶段,通常会执行清理操作,例如删除旧版本的缓存。这确保了新版本的Service Worker可以顺利接管,同时也有助于清理不再需要的缓存。

  • 激活后(Active):Service Worker在激活后一直保持活动状态,可以拦截请求并执行后台任务,如后台数据同步和推送通知。它的活动状态使其能够快速响应事件,提高了插件的性能。

  • 终止(Termination):如果Service Worker长时间没有活动,浏览器可能会终止它以释放资源。然而,需要注意的是,即使在休眠期间,Service Worker仍然可以接收和处理消息,但不会执行重量级的任务,以避免影响性能。

Service Worker通常用于实现离线支持、提高性能和后台数据同步等功能,Service Worker 作为一个后台稳定运行的脚本,一些耗时的操作一般放在Service Worker中进行离线处理,同时Service Worker 还可以作为消息中转站

Service Worker作为后台的脚本,是没有浏览器环境的,无法使用window对象,只有chrome对象,在service worker中可以使用考虑定时器定时唤醒service workder来确保它一直在后台运行,当然会比较消耗用户的资源

2. Content Scripts

Content Scripts是可以嵌入到浏览页面中的脚本,其主要任务是与页面进行交互。以下是Content Scripts的工作流程:

  • 注入(Injection):Content Scripts在浏览器加载页面时注入到页面中,并可以访问页面的DOM和JavaScript环境。这使它们能够与页面内容进行交互。

  • 执行(Execution):它们可以修改页面的内容和样式,响应用户的交互事件,并与页面上的JavaScript代码进行通信。这使它们能够添加额外的功能或修改页面的外观和行为。

  • 销毁(Termination):当页面卸载或关闭时,Content Scripts会被销毁,以释放资源。

Content Scripts通常用于在网页中添加额外的功能、修改页面的外观和行为,以及与页面的JavaScript代码交互,但是Content Scripts 无法访问到页面的JavaScript代码,只能访问和修改页面上的dom元素,相当于在页面上引用了一段script 代码,如果注入页面也是由你控制的,可以通过一些手段与插件通讯,如postmessage等。

Content Scripts 是注入在浏览器页面中运行,能够与浏览器页面共用window对象,也能够使用部分chrome对象API

3. 插件内部网页(Popup)

插件内部网页,通常是弹出式页面(Popup),用于显示插件的设置、选项或与用户的交互界面。以下是Popup的工作流程:

  • 创建(Creation):Popup在用户点击插件图标时创建并显示,通常用于配置插件的设置。这是与用户直接交互的主要界面。

  • 交互(Interaction):用户可以在Popup页面上与插件进行交互,执行操作或修改设置。这使得Popup可以用于执行与插件功能相关的任务。

  • 销毁(Termination):当用户关闭Popup时,它会被销毁,以释放资源。

Popup通常用于提供用户友好的界面、配置插件的设置和执行与插件功能相关的任务。

Popup 通常无法由开发者打卡或者关闭,只有用户点击工具栏中的拓展程序Popup会自动创建,用户点击了其他地方后,Popup会被自动销毁

通信方式

不同组件之间的通信通常需要通过Service Worker脚本作为中介来实现。以下是通信示例:

向Content Scripts发送消息:

  1. 在Service Worker脚本中使用chrome.tabs.query来查找正在运行Content Scripts的标签页,并向其发送消息。

  2. Content Scripts需要通过chrome.runtime.onMessage来监听和响应这些消息。

在Service Worker脚本中向Content Scripts发送消息:

// 查询匹配的标签页
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
  // 向Content Scripts发送消息
  chrome.tabs.sendMessage(tabs[0].id, { from: 'Service Worker', message: 'Hello from Service Worker' });
});

在Content Scripts中监听消息:

// 在Content Scripts中监听来自Service Worker的消息
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
  if (message.from === 'Service Worker') {
    console.log('Received message in Content Script:', message.message);
    // 执行相应操作
  }
});

这种方式通过background脚本将消息发送给Content Scripts,确保了消息可以正确传递到Content Scripts中。

向Popup发送消息:

  1. Popup页面可以使用chrome.runtime.sendMessage向background脚本发送消息。

  2. Service Worker脚本可以将接收到的消息转发给Popup页面。

  3. Popup页面需要通过chrome.runtime.onMessage来监听和响应这些消息。

Background向Popup发送消息:

// 在Service Worker脚本中发送消息到popup页面
chrome.runtime.sendMessage({from: 'Service Worker',message: "Hello from Service Worker!"});

Content Scripts 向Popup 发送消息: 由于content 和 popup 运行在不同的环境,需要借助background进行消息转发 content 向background 发送消息

// content 向Service Worker发送消息
chrome.runtime.sendMessage({from:'content', to:'popup', message:'Hello from content!'}, function (response) {
    console.log('收到回复消息:', response)
  });

Service Worker接受消息并转发给popup

// 在Service Worker脚本中接收消息,并转发给Popup页面
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
  if (message.from === 'content' && message.to === 'popup') {
    // 转发消息给Popup页面
    chrome.runtime.sendMessage(message, function (response) { // 注册了一个回调函数,来获取消息接收者返回的信息
   	 console.log('收到回复消息:', response)
   	 sendResponse(response)
  	});
  }
});

在Popup页面中监听消息:

// 在Popup页面中监听来自Service Worker的消息
chrome.runtime.onMessage.addListener(function(message

, sender, sendResponse) {
  if (message.from === 'content' && message.to === 'popup') {
    console.log('Received message in Popup:', message.message);
    // 执行相应操作
    const response = 'nothing'
    sendResponse(response)
  }
});

消息传递的API支持异步的方式,返回一个promise,但是如果使用异步消息传递则回调函数无法正确触发(sendResponse:消息接收者接收到消息后可以使用sendResponse将处理后的结果发送给消息发送者)

需要注意的是:popup 与 content 是依赖用户行为的,用户可以选择将页面关闭,此时消息窗口会被关闭