Chrome瀏覽器擴充套件外掛教程:從MV2遷移到Manifest V3

語言: CN / TW / HK

Chrome Web Store於2021年1月已經開始接受Manifest V3擴充套件的提交。如果你還在使用MV2版本,那麼一定要在官方棄用之前,儘快更新到MV3版本。

Chrome瀏覽器從88版本開始支援MV3啦(即Manifest Version 3),目前檢視官方文件時預設已經是MV3版本。

我們這篇文章主要了解3個問題

1、MV2的棄用時間表

2、瞭解MV3的新特性

3、如何將MV2遷移到MV3

一、Manifest V2棄用時間表

此圖表指定了棄用Manifest V2(MV2)的時間表

  • 2022年1月份開始不接受新的MV2版本(除了”私人”可見型別),開發者可以更新已經存在的MV2擴充套件外掛
  • 2022年6月份不接受新的MV2版本,開發者可以更新已經存在的MV2擴充套件外掛
  • 2023年1月份開始,開發者不能更新MV2的擴充套件外掛,MV2也不能在Chrome瀏覽器執行(除了個別的企業版)
  • 2023年6月份MV2版本將不能在Chrome瀏覽器執行

二、Manifest V3新特性

Manifest V3是十年前推出擴充套件平臺以來最大的轉變之一。Manifest V3的新的擴充套件規範將在安全性、私密性和效能方面得到增強;也可以使用Manifest V3中採用的更現代的開放網路技術,比如Service Worker和Promises。並會逐步淘汰Manifest V2。

MV3新特性概要

declarativentrequest API

三、如何將MV2遷移到MV3

1、修改manifest.json

1)manifest.json版本號

顯而易見第一步需求修改 manifest.json 檔案

{
    ...,
    "manifest_version": 3,
    ...
}

2)Host Permissions

在Manifest V2中,有兩種方法為你的api或任何主機獲得許可權,要麼在 permissions 陣列或 optional_permissions 陣列。

在Manifest V3中,所有主機許可權現在都單獨存在一個新陣列中,該陣列的鍵為 host_permissions 。主機許可權不再與其他許可權一起新增。

MV2

{
    ...,
    "permissions": [
        "http://tahub.app/*"
      ],
    ...
}

MV3

{
    ...,
    "host_permissions": [
        "http://tahub.app/*"
      ],
    ...
}

3)Background Scripts

Manifest V3用Service Worker替換了 background scripts。

MV2 Background物件目前看起來是這樣的:

{
    ...,
    "background": {
        "scripts": ["assets/js/background.js"],
        "persistent": false
      },
    ...
}

我們需要做的是把 script 陣列的鍵改為 service_worker ,替換多個background pages或scripts。所以,它應該是這樣的:

{
    ...,
    "background": {
        "service_worker": "assets/js/background.js"
      },
    ...
}

注意,我們不再需要新增 persistent 了。

4)Actions

Actions 過去是 browser_actionpage_action ,但現在它們在Manifest V3中統一為 Actions 。這是因為隨著時間的推移,分開他們變得沒有必要。

MV2

// Manifest V2

// manifest.json
{
  "browser_action": { … },
  "page_action": { … }
}

// background.js
chrome.browserAction.onClicked.addListener(tab => { … });
chrome.pageAction.onClicked.addListener(tab => { … });

MV3

// Manifest V3

// manifest.json
{
  "action": { … }
}

// background.js
chrome.action.onClicked.addListener(tab => { … });

5)Content Security Policy (CSP)

你需要改變它從一個String(在Manifest V2)到一個Object(在Manifest v3)。

MV2

// Manifest V2

"content_security_policy": "..."

MV3

// Manifest V3

"content_security_policy": {
  "extension_pages": "...",
  "sandbox": "..."
}

6)Web-Accessible Resources

web_accessible_resources 陣列更改為一個詳細描述所有資源的物件,每個物件都可以對映到到一組url或擴充套件id。下面是V3版本的一個例子:

MV2

// Manifest V2

"web_accessible_resources": [
  RESOURCE_PATHS
]

MV3

// Manifest V3

"web_accessible_resources": [{
  "resources": [RESOURCE_PATHS]
}]

此外還支援其它的屬性,用於設定不同的規則: matchesextension_idsuse_dynamic_url

2、將 Background Scripts 改造成 Service Workers

首先,什麼是service worker,它和background scripts有什麼不同?

background scripts在幾乎所有擴充套件中都是必不可少的。允許執行一些操作或執行程式碼,而不需要使用者開啟某個頁面或執行某些操作。這可以用於傳送通知、與content scripts通訊等等。後臺指令碼通常總是在後臺執行。

Service worker在需要的時候被執行。與後臺指令碼不同,它們並不總是在後臺執行。在最頂層,service worker將監聽器註冊到一些事件中,以允許它們稍後被執行。

從background scripts到service worker的轉換依賴於擴充套件中的程式碼。一些擴充套件可能需要大量的工作,而另一些則不需要這麼多。

需要做的第一步是將以前作為background scripts檔案移動到根目錄。

{
    ...,
    "background": {
        "service_worker": "background.js"
      },
    ...
}

現在,讓我們看看程式碼。以前的background script如下:

chrome.runtime.onMessage.addListener(function(message, sender, senderResponse){
  if(message.msg === "image"){
    fetch('http://some-random-api.com/img/xxx')
          .then(response => response.text())
          .then(data => {
            let dataObj = JSON.parse(data);
            senderResponse({data: dataObj, index: message.index});
          })
          .catch(error => console.log("error", error))
      return true; 
  }
});

基本上,我們的後臺指令碼使用 chrome.runtime.onMessage.addListener 來監聽一個訊息,如果該訊息請求一個圖片,它將向API傳送一個請求,然後將資料返回給我們的content script。

這個background script實際上不需要任何額外的更改。因為service worker的後臺指令碼只是註冊了一個事件監聽器,並在事件發生時執行程式碼,這正是service worker應該做的。

但並不是所有的擴充套件都是這樣的,因為有不同的情況。以下是你在background script中需要檢查和修改的內容:

1) 全域性變數

以前的後臺指令碼總是在後臺執行。如果有以下程式碼:

let count = 0;

chrome.runtime.onMessage.addListener( (message) => {
    count++;
    console.log(count);
});

每當service worker收到一條訊息時,count就會增加。一開始是0,然後是1,然後是2,以此類推。

在service worker中,這將不再有效。service worker只會在需要時執行,並在完成工作時終止。因此,上述程式碼將始終在控制檯列印“1”。

在上面的例子中,計數可以在background script和content script之間來回傳遞,以獲得所需的結果。更好的方法是使用Chrome的儲存API。

2) Timers and Alarms

Timers 在後臺指令碼中使用沒有問題,因為它們總是在後臺執行。然而,這不適用於服務工作者。你應該用 Alarms API 替換所有的計時器。

3) 訪問DOM

Service worker不能訪問windows或DOM。如果你的擴充套件需要,你可以使用類似 jsdom 的庫或使用chrome.windows.create和chrome.tabs.create。這取決於你的具體使用場景。

如果你的background scripts有錄製音訊或視訊,這也是需要修改的,因為這在service worker中是不可以的。

4) 建立Canvas

如果你的background scripts之前建立了畫布,你仍然可以用 offscreenenccanvas API 來做。你所要做的就是用 OffscreenCanvas 替換 document

MV2

let canvas = document.createElement('canvas');

MV3

let canvas = new OffscreenCanvas(width, height);

在完成這些修改之後,需要將你的background scripts 修改為service worker,在瀏覽器中重新載入你的擴充套件,看看它是否正常工作。

5) 執行指令碼executeScript

如果你的程式碼使用executeScript的code屬性執行任意字串,有兩種方法來更改它。同時,不使用chrome.tabs.execute指令碼,需要用 script 替換標籤,這樣它將是 chrome.script .executeScript

將程式碼移植到檔案

你需要將程式碼的值移動到一個新檔案,並使用executeScript的 file 屬性。

之前

chrome.tabs.executeScript({
    code: alert("Hello, World!")
});

修改為

alert(“Hello, World!”) 放到一個新檔案(讓我們叫它 Hello - World .js ):

alert("Hello, World!");
chrome.scripting.executeScript({
    file: 'hello-world.js'
});

將程式碼放到Function中

如果你的程式碼可以放在一個函式中,可以將它移動到同一個檔案中的一個函式中,然後將execute escripts的 function 屬性賦值給你建立的函式:

function greeting() {
    alert("Hello, World!");
}

chrome.scripting.executeScript({
    function: greeting
});

3、其它需求檢查的

這裡有一個列表,列出了你需要在程式碼中尋找的要更改的內容:

1、如果你的擴充套件使用 webRequest API ,它通常用於強制安裝擴充套件的企業設定,你需要用 declarativentrequest API 替換它。

2、如果你在內容指令碼中發出任何CORS請求,請將它們移動到service worker中。

3、不再允許遠端託管程式碼。你需要找到另一種方法來執行遠端託管的程式碼。Chrome的文件建議使用 配置驅動功能和邏輯 ,這個意思就是說將配置本地化,然後執行用遠端的web服務來執行。

4、請檢視 API參考 ,瞭解可能正在使用的已棄用的API或方法。

好了,以上就是本篇主要內容,Manifest V3的新特性讓擴充套件更安全,其實長遠看是有好處的,這樣瀏覽器擴充套件也不會被濫用,只是之前的MV2一些用法和寫法需要做一些調整,工作量應該不會很大,逐條檢查自己產品中存在的問題,相信問題一定能夠解決,祝大家產品越做越好!