Chrome 插件特性及實戰場景案例分析
作者:vivo 互聯網前端團隊 - Zhang hao
一、前言
提起 Chrome 擴展插件 (Chrome Extension),每個人的瀏覽器中或多或少都安裝了幾個插件,像一鍵翻譯、廣告屏蔽、錄屏等等,通過使用這些插件,可以有效的提高我們的工作效率;但有時候,我們想要的某個功能市面上沒有現成的插件,作爲開發者自然而然想到,自己是否可以動手開發一個定製化的插件?網上目前很多不錯的關於 Chrome 插件的開發教程,可以幫助我們快速上手開發一個插件, 本文換個思路,從應用着手,通過講解插件的特性來啓發讀者在工作中哪些場景可以通過插件來解決。
本文側重點不是 Chrome 插件的基礎開發,而是聚焦於原理及應用,會從插件的一些重要特性講起,結合實際的插件案例,來分析這些特性的作用,從而能夠啓發讀者利用這些特性開發出自己的效率工具,打造自己的趁手利器。
二、什麼是 Chrome 擴展插件
什麼是 Chrome 擴展插件?在我們印象中,它就像跑在瀏覽器中的應用,可以把瀏覽器想象成手機,那麼插件就像是應用,我們從 Chrome 應用商店中下載,然後安裝到 Chrome 瀏覽器中,就可以在瀏覽器中進行運行了。
我們看看官方解釋:
Chrome Extension 是一個小的軟件程序,它可以用來定義瀏覽器的瀏覽體驗,讓用戶可以根據個人需求或者偏好定製 Chrome 瀏覽器的功能和行爲,主要使用的技術棧是 HTML、Javascript 和 CSS。
一句話總結:Chrome 擴展插件是用前端的技術棧,來定製瀏覽器的功能,改善用戶體驗。
可能大家還聽過一個詞:Chrome Plugin。翻譯過來是 Chrome 插件,和 Chrome 擴展插件很相近,特別容易搞混,那麼他們之間有什麼區別呢?
-
Chrome Extension 僅僅是用來增強瀏覽器網頁的功能,它是利用瀏覽器提供的已有功能和和各種 API,進行功能組合,從而改善瀏覽器體驗,停留在瀏覽器層面;
-
Chrome Plugin 不僅能增強網頁的功能,同時能夠擴展瀏覽器本身的功能;當瀏覽器提供的功能已經無法滿足你的需求,就需要你通過 C/C++ 這樣的編譯語言來擴展瀏覽器的功能,例如我們常用的 Flash 插件,Chrome Plugin 工作在內核層面。
三、Chrome 擴展插件組成及核心機制
3.1 Chrome 擴展插件的組成
一個 Chrome 擴展插件通常由 3 類文件組成:
1) 配置文件 manifest.json,用於配置擴展的名稱、版本號、作者、圖標 icon、彈出界面、權限、腳本路徑等信息;
2) 圖片、css 等資源文件;
3)js 腳本文件,其中包含:
-
popup.js:用於搭配 popup.html 使用,點擊插件圖標的時候展示頁面及頁面邏輯控制;
-
background.js:用於定義一個後臺頁面,相當於一個常駐頁面,生命週期和瀏覽器一致;
-
content_scripts.js:用於向頁面中注入 JS 腳本,它可以操作頁面 dom,但不會和頁面中的腳本產生衝突。
3.2 Chrome 擴展插件的核心機制
Chrome 擴展插件中比較核心的幾個概念:Extension Page、background.js、Content_script.js ,它們在什麼時機觸發,扮演着什麼角色,彼此之間如何進行通信?可以看一下下面的關係圖:
從圖中可以看出,存在三個進程:擴展進程(Extension Process)、頁面渲染進程(Render Process)、瀏覽器進程(Browser Process)。
1)擴展進程中運行 Extension Page,Extension Page 主要包括 backgrount.html 和 popup.html:
-
backgrount.html 中沒有任何內容,是通過 background.js 創建生成,當瀏覽器打開時,會自動加載插件的 background.js 文件,它獨立於網頁並且一直運行在後臺,它主要通過調用瀏覽器提供的 API 和瀏覽器進行交互;
-
popup.html 則不同,它有內容,是一個實實在在的頁面,和我們普通的 web 頁面一樣,由 html、css、Javascript 組成,它是按需加載的,需要用戶去點擊地址欄的按鈕去觸發,才能彈出頁面。
2)渲染進程主要運行 Web Page, 當打開頁面時,會將 content_script.js 加載並注入到該網頁的環境中,它和網頁中引入的 Javascript 一樣,可以操作該網頁的 DOM Tree,改變頁面的展示效果;
3)瀏覽器進程在這裏更多起到橋樑作用,作爲中轉可以實現 Extension Page 和 Content_script.js 之間的消息通信。
四、Chrome 擴展插件能做什麼
Chrome 擴展插件的使用方向主要包含兩個部分:
改變瀏覽器的外觀:
-
brower Actions
-
page Actions
-
content menus
-
桌面通知
-
Omnibox
-
override 替代頁
和瀏覽器進行交互:
-
Cookie 控制
-
標籤控制
-
書籤控制
-
下載控制
-
事件監聽
-
網絡請求
-
代理...
下面我們通過實例來分析這些功能的使用案例:
實例 1: 替換頁面
使用替代頁,可以將 Chrome 默認的一些特定頁面替換掉,改爲使用擴展提供的頁面。這讓開發者可以開發更多有趣或者實用的基本功能頁面。
"chrome_url_overrides": {
"newtab": "newTab.html", //替換新標籤頁
"bookmarks":"bookmarks.html", //替換書籤管理器頁面
"history":"history.html" //替換歷史記錄頁面
},
下面是一個替換新標籤頁的效果圖:
實例 2:Cookie 控制
通過 Cookie 的 API,可以對瀏覽器的 Cookie 進行增刪改查工作。例如我們在開發工作中,經常需要頻繁的清除瀏覽器緩存,每次都需要先找到清除按鈕,彈出對話框,進行確認,操作很繁瑣,如果開發一個 chrome 擴展插件,就可以輕鬆實現一鍵快捷清除瀏覽器 Cookie 等緩存,可以參考 Clear Store 插件。
**實例 3:標籤控制 **
使用 chrome.tabs API 與瀏覽器的標籤系統進行交互,可以查詢,創建、修改和重新排列瀏覽器中的標籤頁; 我們在使用瀏覽器時,經常會打開很多標籤頁,顯得很混亂,中途想要找打開的某個頁面時,效率低且痛苦,如果能將這些標籤頁進行整理並有序的展示該多好,這裏給大家推薦一個 Chrome 擴展插件:OneTab,該插件將所有打開的標籤頁在新的頁面中有序的排列出來,如下圖,一目瞭然。
我們甚至可以通過 tabs 實現頁籤之間的交互,出於安全考慮,tab 的屬性中沒有 document, 因此無法在擴展中直接獲取某個標籤頁面中的 dom 元素,但是可以通過發送事件請求來實現:
chrome.tabs.sendRequest(tab_id, {
hello: "ok"
}, function(response){
// response處理
});
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
if (request.hello == "ok"){
sendResponse({
data: $("#hello") // 獲取id是hello的元素髮過去
});
}
}
);
實例 4:攔截請求或者反向代理
在在頁面性能點檢時,我們經常會檢查頁面圖片資源是否存在尺寸過大,例如 200K,獲取一個過大的圖片列表頁面。
chrome.webRequest API 只能在 background.js 中使用,所以可以通過圖片攔截,將鏈接通過消息傳給當前頁面的 content_script.js,然後在 content_script.js 中進行圖片下載和大小檢查。
// background.js
chrome.webRequest.onBeforeRequest.addListener(
function(details) {
// url就是圖片下載的鏈接
const { url ,tabId} = details
// 向content_script.js發送下載圖片鏈接
chrome.tabs.sendMessage(tabId, {picUrl: url}, function(response) {
//...
});
return {cancel: isCancel};
},
{urls: ["http://baidu.com"],types: "image"},
["blocking"]
);
// content_script.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse)
{
if(sender.tab && request.picUrl && request.picUrl == sender.tab.id){
//獲取圖片大小並下載
}
});
實例 5:頁面元素操作
利用 Content_script.js 可操作 dom 元素,進行對頁面元素進行操作,實現自動化登錄,解放雙手。
//輸入
function input(inputElement, content) {
let event = document.createEvent('HTMLEvents');
event.initEvent('input', true, true);
inputElement.value = content;
inputElement.dispatchEvent(event)
}
const usernameDom = document.getElementById("userName"); //用戶名
const pwdDom = document.getElementById("password"); //密碼
const btnDom = document.getElementById("submitBtn");//按鈕
//輸入後,點擊確認
input(usernameDom, "姓名");
input(pwdDom, "密碼");
//登錄
btnDom.click();
五、業務實踐
痛點:我目前主要負責 vivo 全球商城的業務,全球化的業務都會面臨國際化語言的問題,我們自主開發了一個多語言管理後臺,配置 key-value, 前端通過接口獲取多語言在頁面展示;如果運營查看頁面,覺得某個文案不太合適,想要修改,需要進行如下圖的一系列操作:
可以看到當運營想要修改文案時,他先要知道該文案對應的 key 值,而頁面上面無法獲取到 key 值,需要讓開發提供,然後需要到多語言管理平臺去更新對應 key 的值。
這樣遇到兩個問題:
-
不能所見即所得,看到頁面不能知道 key 值;
-
所見無法直接修改,需要到另一個管理平臺去修改 ;
目前這個在修改內容少的情況下,還是可以操作的,當修改內容很多時,這樣操作起來很繁瑣,效率很低。
思考:
1)運營是否可以直接在頁面上修改並生效?
2)如果可以修改,怎麼去實現跨域請求?
3)怎麼實現登錄授權?
如果對 Chrome 擴展插件熟悉,會發現 Chrome 就是爲這量身定製,可以完美解決這些問題。
**實現方案: **
1)對頁面中涉及文案 dom 進行修改,綁定多語言 key 值。
<div data-lang-key="address.delete.button">{{ language.addressDeleteButton }}</div>
2)利用 Content_script,js 可以操作頁面 dom 元素,當啓動插件時,將頁面所有可修改的文案的 dom 增加 contenteditable 屬性,支持可編輯,如圖;
3)創建一個修改面板,獲取當前選中的 key 值和 value 值,和修改後的值,如上圖,右上角面板。
4)利用 Chrome 插件支持跨站請求的特性,向多語言平臺直接發送修改請求。
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
try{
sendResponse(JSON.parse(xhr.response));
}catch(e) {
// 異常處理
}
}
};
xhr.send(new URLSearchParams(params));
return true
}
);
5)利用 Chrome 插件可以獲取瀏覽器中 Cookie 特性,新開一個標籤頁打開多語言後臺,進行登錄,登錄成功後就可以實現請求的授權修改了。
六、總結
最後總結一下,生活中經常會感嘆:看過好多人生道理,依然過不好這一生。同樣,使用過很多 Chrome 插件,依然碼不好自己的一個插件,所以最後再送給你一個閱讀 Chrome 插件源碼的插件,堪稱插件中的插件,插件中的王者——**Chrome extension source viewer。**通過它可以很方便的查看其它插件的源碼,讓我們能夠站在巨人的肩膀上往前走~~
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/fmjjwpJSZ7tA2eAPnz3hkw