在昨天的實作中,我們使用到了 chrome.runtime.sendMessage
這個 API
今天來介紹一下!
在 Chrome Extension 的架構中,不同模組(content script、background、popup)運作在不同的環境,彼此之間不能直接呼叫函式或共享變數。
這時就需要透過 Message Passing(訊息傳遞機制) 來讓它們彼此交換資料。
這三者各自的環境是隔離的,無法直接共享變數,因此必須透過 message passing(訊息傳遞) 來協調。
[ content_script ] ⇔ [ background.js ] ⇔ [ popup.html / popup.js ]
適合 簡單請求-回應 的場景,例如:popup 要求 content script 傳回目前頁面的 MR 標題。
範例:popup → content script
//popup.html
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, { action: "getMRTitle" }, (response) => {
console.log("MR 標題:", response.title);
});
});
// content-script.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === "getMRTitle") {
const title = document.querySelector(".merge-request-title")?.innerText;
sendResponse({ title });
}
});
因為 Chrome 提供了 chrome.tabs.sendMessage
API。
雖然程式碼是「在 popup 裡呼叫 sendMessage 傳給 content script」,
但實際上,這個 API 會繞過 background,直接幫你轉送到指定的 tab 的 content script。
也就是說:
不算衝突,而是 不同層次的說明:
適合需要 持續交換訊息 的情境,例如 background 跟 content script 持續同步資料。
建立連線
// content-script.js
const port = chrome.runtime.connect({ name: "myChannel" });
port.postMessage({ msg: "Hello from content!" });
port.onMessage.addListener((msg) => {
console.log("收到 background 回覆:", msg);
});
// background.js
chrome.runtime.onConnect.addListener((port) => {
console.log("有連線建立:", port.name);
port.onMessage.addListener((msg) => {
console.log("來自 content 的訊息:", msg);
port.postMessage({ reply: "Got it!" });
});
});
假設我們想要:
流程:
這就是 典型的三層 Message Passing 流程。