第三部分 — 服务工作者(后台)chrome.runtime 是什么(在 MV3 的说法中)

chrome.runtime 是扩展内的"粘合剂" API:

  • 生命周期事件(安装/更新)

  • 身份 (runtime.id, getURL)

  • 轻量级消息入口点

  • 通过 chrome.runtime.lastError 的错误处理层(针对回调 API)

如果从 MV2 迁移过来:将 chrome.runtime 视作 稳定协调层, 位于 UI 页面、服务工作者、内容脚本之间(可选地) 与离屏文档之间。

7.2 runtime.id, getURL,以及环境假设

javascript 复制代码
console.log("extension id:", chrome.runtime.id); 
console.log("options url:", chrome.runtime.getURL("options.html"));

注意事项:

  • 除非在企业部署流程中,否则不要硬编码扩展ID。

  • 对于内部资源,请使用 getURL()。 它可以适应打包差异。

7.3 实际使用的 onInstalled 细节

javascript 复制代码
chrome.runtime.onInstalled.addListener((details) => {
  console.log("onInstalled:", details.reason, details.previousVersion);

  if (details.reason === "install") {
    // One-time setup: defaults, onboarding, etc.
  }

  if (details.reason === "update") {
    // Migration: version-based transforms.
  }
});

设计规则: 数据迁移必须是幂等的,并且在需要时可以安全地重新运行。

7.4 消息入口点:onMessage(以及异步陷阱)

最小模式(异步响应):

javascript 复制代码
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  (async () => {
    if (msg.type !== "PING") return;
    sendResponse({ ok: true, from: "sw" });
  })().catch((err) => {
    sendResponse({ ok: false, error: String(err) });
  });

  // Critical in MV3: keep the channel open for async.
  return true;
});
复制代码

** Pitfalls:**

  • 忘记添加 return true → 间歇性"消息通道关闭"失败。

  • 不验证 sender → 多个上下文发送消息时的安全/逻辑漏洞。

7.5 始终验证 sender(最小安全检查)

javascript 复制代码
function assertSender(sender) {
  // Example: only accept messages from your own extension pages.
  if (sender.id !== chrome.runtime.id) {
    throw new Error("Unexpected sender.id");
  }
}

chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  try {
    assertSender(sender);
    sendResponse({ ok: true });
  } catch (e) {
    sendResponse({ ok: false, error: String(e) });
  }
});

7.6 回调错误:chrome.runtime.lastError(当适用时)

规则: 只在回调内部检查 lastError。

javascript 复制代码
chrome.runtime.getPlatformInfo((info) => {
  if (chrome.runtime.lastError) {
    console.error(chrome.runtime.lastError.message);
    return;
  }
  console.log(info);
});
复制代码

陷阱: 在回调之外检查 lastError 没有意义。

7.7 connect vs sendMessage(决策点)

  • 使用 sendMessage 进行请求/响应操作。

  • 当你需要以下功能时使用 connect (端口):

  • 流式进度

  • 长期协调

  • 重连逻辑(特别是在 SW 重启时)

(端口在第四部分有深入介绍。)

最小示例

一个最小的 MV3 安全异步消息处理器(适合作为模板):

javascript 复制代码
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
  (async () => {
    if (msg?.type !== "PING") return;
    sendResponse({ ok: true });
  })().catch((err) => sendResponse({ ok: false, error: String(err) }));
  return true; // keep channel open for async
});

常见陷阱

  • 依赖隐式的状态(全局变量)而不是持久化的存储

  • 假设 MV3 提供的时间/生命周期保证实际上并不提供

  • 过度请求权限/宿主访问

7.8 检查清单

  • 不要硬编码扩展 ID(除非企业版)

  • onInstalled 的迁移操作是幂等的

  • 所有异步 onMessage 处理函数都返回 true

  • 验证 sender 至少通过 sender.id

  • 对于回调 API:在回调中检查 runtime.lastError

7.9 参考

相关推荐
alexander0686 分钟前
CSS 类选择器组合
前端·css
寅时码5 小时前
React 之死·终章:一个 useRef,把闭包陷阱、依赖数组、漫天 rerender 全送走
前端·react.js·ai编程
不好听6135 小时前
HTML 事件监听机制:从 DOM Level 0 到 React 合成事件
前端·react.js·html
wordbaby5 小时前
为什么刷新页面就 404?聊聊 SPA 路由与 Nginx 的那点事
前端
daols885 小时前
vxe-table 渲染器教程一:实现金额输入控件
javascript·vue.js·vxe-table
不好听6136 小时前
React 核心概念:JSX、组件与数据驱动
前端·react.js
触底反弹6 小时前
🔥 React 零基础入门(中):500 行屎山代码到组件化的蜕变
前端·javascript·react.js
不好听6136 小时前
React vs Vue:两大前端框架技术选型深度对比
前端·vue.js·react.js
GuWenyue6 小时前
Cursor黑盒拆解!1套LangChain.js手写Mini编程Agent,自动生成React项目,效率提升60%
前端·数据库·人工智能
GuWenyue6 小时前
传统Agent工具两大痛点!300行代码落地MCP跨语言工具,彻底解耦LLM与工具
前端·人工智能·算法