第三部分 — 服务工作者(后台)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 参考

相关推荐
echome8886 分钟前
CSS 布局:Flex 和 Grid 怎么选,附常见坑
前端·css·html
计算机魔术师12 分钟前
科技巨头砸7400亿押注AI,为什么苹果成了唯一赢家?
前端
系统集成-鹰翔20 分钟前
ERP推单数据库怎么备份:SQLite WAL模式下只复制db文件为什么可能漏任务
javascript·数据库·经验分享·后端
QianhangQianping22 分钟前
撤销重做不是「存快照」:一个可视化编辑器的Operation 设计
java·前端·数据库·typescript·编辑器·前端架构·撤销重做
Nymph_Zhu1 小时前
pdf转换markdown预览及内容互相点击定位
前端·pdf·vue3·markdown·element-plus
计算机魔术师1 小时前
Google 一天蒸发5000亿,Reddit 靠 AI 训练喂得饱自己却饿死
前端
小大宇1 小时前
Vue知识点-ElementPlus-05 输入框
前端·javascript·vue.js
外贸GEO优化2 小时前
外贸独立站的可抓取性:JS 渲染、懒加载与无限滚动到底影响什么
开发语言·javascript·ecmascript
l1m0_2 小时前
AI设计工具有哪些?Paico、Pixso AI、墨刀AI、Lovable、Codex怎么选
前端·人工智能·ai·设计·墨刀·codex·pixso
web打印社区2 小时前
Lodop在Edge和双核浏览器-先分清内核
前端·javascript·edge·pdf·ecmascript·html5