前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >简化Web扩展中的消息传递:WebExt-Bridge的使用指南

简化Web扩展中的消息传递:WebExt-Bridge的使用指南

作者头像
訾博ZiBo
发布2025-01-06 20:56:14
发布2025-01-06 20:56:14
12400
代码可运行
举报
运行总次数:0
代码可运行

简化Web扩展中的消息传递:WebExt-Bridge的使用指南

在开发Web扩展时,各个组件之间的通信是必不可少的,但这项任务往往充满挑战。不同的浏览器对消息传递的处理略有不同,导致我们在确定消息发送目标时可能会遇到复杂的情况。为了解决这个问题,WebExt-Bridge提供了一个简单而一致的API,可以在Web扩展的不同部分之间(如background、content-script、devtools、popup、options和window上下文)发送消息。

一、简介

WebExt-Bridge 的设计初衷是简化 Web 扩展中各部分之间的通信。无论是在后台脚本、内容脚本、开发者工具、弹出窗口、选项页还是窗口上下文之间,WebExt-Bridge 都能提供一个高效且一致的方式来发送和接收消息。该包已在生产环境中经过广泛测试,例如在 Bugflow 项目中得到了应用。

WebExt-Bridge 项目最初由 Neek Sandhu(@zikaari)于 2017 年启动,现已由 Server Side Up 接手维护。我们感谢 Neek Sandhu 的贡献,并期待在未来继续推动这一项目的发展。

官网:https://serversideup.net/open-source/webext-bridge/

GitHub仓库:https://github.com/serversideup/webext-bridge

二、安装

你可以通过NPM或Yarn轻松安装WebExt-Bridge:

代码语言:javascript
代码运行次数:0
复制
# 使用NPM
npm i webext-bridge

# 使用Yarn
yarn add webext-bridge

安装完成后,你就可以在扩展的不同组件之间简单地传递消息了。

三、快速示例

接下来,让我们看一个从弹出窗口向后台脚本发送消息的快速示例:

1、弹出窗口

在你的弹出窗口中,添加以下代码:

代码语言:javascript
代码运行次数:0
复制
import { sendMessage } from "webext-bridge/popup";

const response = await sendMessage("ACTION", { data: data }, "background");

2、后台服务工作者

在后台服务工作者脚本中添加以下代码:

代码语言:javascript
代码运行次数:0
复制
import { onMessage } from "webext-bridge/background";

onMessage("ACTION", runAction);

async function runAction({ data }) {
    // 处理数据
    // 返回数据
    return {};
}

就是这样!你已准备好在扩展的不同部分之间发送消息了。

四、优势

使用WebExt-Bridge的最大优势在于它简化了消息传递的过程。与传统的chrome.runtime.sendMessagechrome.runtime.connect方法相比,WebExt-Bridge使得代码更加简洁易读,并允许你更具体地指定消息的发送和处理位置。它还支持跨平台的解决方案,代码可以在Firefox、Chrome、Safari和Edge上运行。

五、深入学习

对于想要深入学习WebExt-Bridge的开发者,我们推荐阅读我们的书籍《构建多平台浏览器扩展》。这本书涵盖了从基础到高级主题,如消息传递、存储和调试,并特别介绍了如何使用WebExt-Bridge来简化扩展中的消息传递。

六、概念与上下文

浏览器扩展由多个上下文组成,每个上下文可以发送和接收消息。WebExt-Bridge支持的上下文包括content-script、popup、options、background和devtools。通过在代码中导入相应的模块,你可以轻松地在这些上下文中进行通信。

1、通信上下文

WebExt-Bridge支持以下几种通信上下文:

  • content-script - 注入到页面的脚本
  • popup - 扩展的弹出窗口
  • options - 选项页面
  • background - 后台脚本
  • devtools - 开发者工具

2、主要API

sendMessage()

方法签名:

代码语言:javascript
代码运行次数:0
复制
sendMessage(messageId: string, data: any, destination: string)

用于向扩展的其他部分发送消息。如果目标端没有监听器,将抛出错误。监听器可以通过 Promise 获取响应。

参数说明:

  • messageId(必填,string):消息的唯一标识符。
  • data(必填,any):需要传递的数据。
  • destination(必填,string):消息的目标地址,如 backgroundpopupcontent-script@<tabId> 等。
onMessage()

方法签名:

代码语言:javascript
代码运行次数:0
复制
onMessage(messageId: string, callback: function)

用于在每个上下文中注册消息监听器,当接收到指定 messageId 的消息时调用回调函数。

参数说明:

  • messageId(必填,string):需要监听的消息标识符。
  • callback(必填,function):处理消息的回调函数,可以返回值或 Promise 作为响应。
allowWindowMessaging()setNamespace()

注意:这是危险操作,仅在必要时使用。

  • allowWindowMessaging(namespace: string):仅在内容脚本中调用,用于解锁特定页面的消息传递通道。
  • setNamespace(namespace: string):在加载的远程页面顶层框架中调用,用于设置消息传递的命名空间,确保消息属于特定的扩展。
openStream()onOpenStreamChannel()

用于在调用者和目标之间打开一个流通道,适用于需要持续通信的场景。

3、类型安全

可以通过定义 Protocol 来实现类型安全:

代码语言:javascript
代码运行次数:0
复制
declare module "webext-bridge" {
  export interface ProtocolMap {
    foo: { title: string }
    bar: ProtocolWithReturn<CustomDataType, CustomReturnType>
  }
}

七、类型安全协议

为了保持协议的类型一致性,WebExt-Bridge提供了类型安全的解决方案。你可以创建一个shim.d.ts文件来定义消息协议的类型,从而在不同上下文中使用时保持一致性。

shim.d.ts文件示例:

代码语言:javascript
代码运行次数:0
复制
import type { ProtocolWithReturn } from 'webext-bridge'

declare module 'webext-bridge' {
  export interface ProtocolMap {
    // define message protocol types
    // see https://github.com/antfu/webext-bridge#type-safe-protocols
    'tab-prev': { title: string | undefined }
    'get-current-tab': ProtocolWithReturn<{ tabId: number }, { title?: string }>
  }
}

八、示例

以下是一些常见的使用示例:

1、弹出窗口 -> 后台脚本

从弹出窗口向后台脚本发送消息

代码语言:javascript
代码运行次数:0
复制
// 弹出窗口脚本
import { sendMessage } from "webext-bridge/popup";

const sendToBackground = async () => {
    await sendMessage("RECORD_NAME", {
        first_name: 'John',
        last_name: 'Doe'
    }, "background");
}

// 后台脚本
import { onMessage } from "webext-bridge/background";

onMessage("RECORD_NAME", recordName);

async function recordName({ data }) {
    // 处理数据
    return {
        // 返回响应
    };
}

2、内容脚本 -> 后台脚本

从内容脚本向后台脚本发送消息

代码语言:javascript
代码运行次数:0
复制
// 内容脚本
import { sendMessage } from "webext-bridge/content-script";

const sendToBackground = async () => {
    const response = await sendMessage('RECORD_NAME', { first_name: 'John', last_name: 'Doe' }, 'background');
    // 处理响应
}

// 后台脚本
import { onMessage } from "webext-bridge/background";

onMessage("RECORD_NAME", recordName);

async function recordName({ data }) {
    // 处理数据
    return {};
}

九、安全性

在处理 window 上下文的消息传递时,需要特别注意安全性。与 chrome.runtime.sendMessagechrome.runtime.connect 不同,WebExt-Bridge 设计上没有限制与扩展通信的站点,这意味着任何网页只要使用相同的协议和命名空间,都可以发送消息。因此,为了确保安全:

  1. 验证消息来源:在回应之前,始终验证发送者的身份。例如,使用 isInternalEndpoint 函数来验证消息是否来自可信的内部端点。
  2. 使用命名空间:通过 allowWindowMessagingsetNamespace 方法,确保只有特定的页面可以与扩展通信,避免恶意网站的干扰。

WebExt-Bridge内置了一些安全机制:

  • 默认只允许扩展内部组件通信
  • 与window上下文通信需要显式允许
  • 提供验证sender的方法

示例

代码语言:javascript
代码运行次数:0
复制
import { onMessage, isInternalEndpoint } from "webext-bridge/background";

onMessage("getUserBrowsingHistory", (message) => {
    const { data, sender } = message;

    // 仅响应来自内部端点的请求
    if (isInternalEndpoint(sender)) {
        const { range } = data;
        return getHistory(range);
    }
});

十、故障排除

如果消息传递不起作用,确保WebExt-Bridge在扩展的背景页面中正确加载,并检查你的背景脚本配置是否正确。

1、消息传递不起作用?

确保 WebExt-Bridge 已在扩展的后台脚本中正确加载。即使你不需要自己的后台页面,也需要添加一个简单的后台脚本来作为消息的中继:

background.js:

代码语言:javascript
代码运行次数:0
复制
import "webext-bridge/background";

manifest.json:

代码语言:javascript
代码运行次数:0
复制
{
    "background": {
        "scripts": ["path/to/transpiled/background.js"]
    }
}

2、无法发送消息给目标?

在向内容脚本发送消息时,必须附加 tabId 以指定脚本所在的标签页。同时,确保在特定标签页的内容脚本中调用 allowWindowMessaging 方法,以允许与 window 上下文的消息传递。

十一、总结

WebExt-Bridge极大地简化了浏览器扩展中的消息传递,是开发扩展必备的工具之一。它提供了:

  • 简单统一的API
  • 类型安全
  • 内置安全机制
  • 跨浏览器兼容

如果你正在开发浏览器扩展,WebExt-Bridge绝对值得一试。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-11-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简化Web扩展中的消息传递:WebExt-Bridge的使用指南
  • 一、简介
  • 二、安装
  • 三、快速示例
    • 1、弹出窗口
    • 2、后台服务工作者
  • 四、优势
  • 五、深入学习
  • 六、概念与上下文
    • 1、通信上下文
    • 2、主要API
      • sendMessage()
      • onMessage()
      • allowWindowMessaging() 和 setNamespace()
      • openStream() 和 onOpenStreamChannel()
      • 3、类型安全
  • 七、类型安全协议
  • 八、示例
    • 1、弹出窗口 -> 后台脚本
    • 2、内容脚本 -> 后台脚本
  • 九、安全性
  • 十、故障排除
    • 1、消息传递不起作用?
    • 2、无法发送消息给目标?
  • 十一、总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档