Chrome 外掛特性及實戰場景案例分析

語言: CN / TW / HK

一、前言

提起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。**通過它可以很方便的檢視其它外掛的原始碼,讓我們能夠站在巨人的肩膀上往前走~~

作者:vivo網際網路前端團隊-Zhang hao