chrome devtools 開發之訊息通訊

hujiao發表於2018-08-05

原文地址:github.com/HuJiaoHJ/bl…

在我們平時的開發工作中,chrome開發者工具是我們必不可少的工具,除了Chrome原生的工具之外,還有比如:

本文主要分享的就是這些開發者工具怎麼與頁面進行訊息通訊的。

首先,先看一個例子:

index

這個開發者工具原始碼:github.com/HuJiaoHJ/ec…,這個工具是一個支援canvas庫 ( easycanvas ) 的chrome除錯工具,能對canvas的元素的樣式、物理屬性等進行修改,達到所見即所得的效果,提高除錯效率。感興趣的小夥伴可以自行了解下~

本文主要是通過這個工具,分享一下 chrome devtools 通訊相關的知識(chrome devtools的基礎開發在這裡就不介紹了,不熟悉的小夥伴可以去官網看看~)當然,沒有接觸過chrome devtools開發的小夥伴,也可以通過這篇文章瞭解到chrome devtools的基本組成,瞭解其基本的通訊方式,對平時的工作也能有一些借鑑和幫助噠~

chrome devtools 簡單介紹

chrome devtools 主要分為三部分:

  • DevTools Page:開發者工具,就是我們平時使用時,接觸到的皮膚
  • Background Page:後臺頁面,雖然叫頁面,其實是在後臺的js指令碼
  • Content Script:內容指令碼,是在網頁的上下文中允許的js檔案

下面會詳細介紹各部分,下面這張圖是這三部分之間的通訊全景圖:

ec-devtools

我們根據這張圖,來詳細的看看每個部分的具體實現吧~

  • 網頁與內容指令碼通訊
  • 內容指令碼與後臺頁面通訊
  • 後臺頁面與開發者工具通訊
  • 網頁的訊息怎麼傳遞到開發者工具?
  • 開發者工具的訊息怎麼傳遞到網頁?

網頁與內容指令碼通訊

內容指令碼(Content Script)是在網頁的上下文中執行的js檔案,可以通過此js檔案獲取DOM和捕獲DOM事件。

網頁不能直接與開發者工具(DevTools Page)進行通訊,需要通過在內容指令碼中監聽網頁事件,通過chrome.runtime API將訊息傳遞到後臺頁面中,從而傳遞到開發者工具中。

內容指令碼可以監聽網頁的DOM事件或者window.postMessage事件,如下:

web page

window.postMessage({
    name: 'hello wolrd'
}, '*');
複製程式碼

content-script.js

window.addEventListener('message', e => {
    if (e.source === window) {
        chrome.runtime.sendMessage(e.data);
    }
});
複製程式碼

內容指令碼與後臺頁面通訊

後臺頁面,雖然叫頁面,其實是在後臺的js指令碼。

內容指令碼監聽的事件觸發之後,通過chrome.runtime.sendMessage()方法將訊息傳遞到後臺頁面(Background Page)中。

後臺指令碼通過chrome.runtime.onMessage.addListener()方法監聽訊息,如下:

background.js

chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (sender.tab) {
        const tabId = sender.tab.id;
        ......
    } else {
        console.log("sender.tab not defined.");
    }
    return true;
});
複製程式碼

後臺頁面與開發者工具通訊

後臺頁面與開發者工具通過長連線進行通訊。(chrome.runtime API)如下:

devtool.js

// 與後臺頁面訊息通訊-長連線
const port = chrome.runtime.connect({name: 'devtools'});
// 監聽後臺頁面訊息
port.onMessage.addListener((message) => {
    ......
});
// 往後臺頁面傳送訊息
port.postMessage({
    name: 'original',
    tabId: chrome.devtools.inspectedWindow.tabId
});
複製程式碼

background.js

chrome.runtime.onConnect.addListener(function (port) {
 
    const extensionListener = function (message, sender, sendResponse) {
        if (message.name == 'original') {
            ......
        }
    };
    port.onMessage.addListener(extensionListener);
 
    port.onDisconnect.addListener(function(port) {
        port.onMessage.removeListener(extensionListener);
    });
});
複製程式碼

以上,就介紹了網頁與內容指令碼、內容指令碼與後臺頁面、後臺頁面與開發者工具之間的通訊,所以可以發現,網頁的訊息是通過內容指令碼、後臺頁面,最後到達開發者工具,那麼達到內容指令碼的訊息怎麼傳遞到開發工具的呢?

網頁的訊息怎麼傳遞到開發者工具?

顯而易見,其實就是通過後臺頁面作為橋,將內容指令碼的訊息傳遞到開發者工具中。具體程式碼如下:

background.js

// 作為content script 與 devtool 通訊的橋
const connections = {};
 
chrome.runtime.onConnect.addListener(function (port) {
 
    const extensionListener = function (message, sender, sendResponse) {
        if (message.name == 'original') {
            connections[message.tabId] = port;
        }
    };
    port.onMessage.addListener(extensionListener);
 
    port.onDisconnect.addListener(function(port) {
        port.onMessage.removeListener(extensionListener);
 
        const tabs = Object.keys(connections);
        for (let i = 0, len = tabs.length; i < len; i++) {
            if (connections[tabs[i]] == port) {
                delete connections[tabs[i]];
                break;
            }
        }
    });
});
 
// 接收內容指令碼的訊息,併傳送到devtool的訊息
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (sender.tab) {
        const tabId = sender.tab.id;
        if (tabId in connections) {
            connections[tabId].postMessage(message);
        } else {
            console.log("Tab not found in connection list.");
        }
    } else {
        console.log("sender.tab not defined.");
    }
    return true;
});
複製程式碼

以上,就完成了網頁的訊息傳遞到開發者工具的過程,那麼開發者工具的訊息怎麼傳遞到網頁?

開發者工具的訊息怎麼傳遞到網頁?

開發者工具的訊息傳遞到網頁主要有兩種方法:

1、直接使用chrome.devtools.inspectedWindow.eval()方法,在網頁的上下文中執行js程式碼,如下:

devtool.js

chrome.devtools.inspectedWindow.eval('console.log(window)');
複製程式碼

2、開發者工具通過長連線將訊息傳遞到後臺頁面,在後臺頁面中,通過呼叫chrome.tab.excuteScript()方法,在網頁中執行js程式碼,如下:

background.js

chrome.tab.excuteScript(tabId, {
    code: 'console.log(window)'
});
複製程式碼

推薦使用第一種方法~

以上,就介紹了網頁與開發者工具之間的通訊全過程啦~~~

以上通訊方式在文章一開始提到的工具都用到了,倉庫:github.com/HuJiaoHJ/ec…,其實也基本涵蓋了 chrome 開發者工具的所有通訊方式~

index

寫在最後

學習了 chrome devtools 的通訊方式之後,就能愉快的開發自己的開發者工具啦,希望能對有需要的小夥伴有幫助~~~

喜歡我的文章小夥伴可以去 我的個人部落格 點star ⭐️

相關文章