關於 chrome 擴充套件的文章,很久之前也寫過一篇。清除頁面廣告?身為前端,自己做一款簡易的chrome擴充套件吧。
本篇文章重在分享一些製作擴充套件的過程中比較重要的知識及難點。
什麼是 chrome 擴充套件程式
擴充套件程式是一些能夠修改或增強 Chrome 瀏覽器功能的小程式。對於前端工程師而言,其最大的便利就是我們可以應用我們熟悉的 HTML、CSS 、 Javascript 等技術來製作擴充套件程式。
如下圖所示,這些圖示就是各種開發者提供的 chrome 擴充套件程式:
區分擴充套件與外掛
很多人會誤稱擴充套件程式為外掛,這裡有必要區分一下。
“擴充套件” 和 “外掛”,其實都是軟體元件的一種形式,Chrome 只不過是把兩種型別的元件分別給與了專有名稱,一個叫 “擴充套件”,另一個叫 “外掛”。
- 擴充套件(Extension)
指的是通過呼叫 Chrome 提供的 Chrome API 來擴充套件瀏覽器功能的一種元件,工作在瀏覽器層面,使用 HTML + Javascript 語言開發。比如著名的 Adblock plus。
- 外掛(Plug-in)
指的是通過呼叫 Webkit 核心 NPAPI 來擴充套件核心功能的一種元件,工作在核心層面,理論上可以用任何一種生成本地二進位制程式的語言開發,比如 C/C++、Delphi 等。比如 Flash player 外掛,就屬於這種型別。一般在網頁中用 <object>或者<embed>
標籤宣告的部分,就要靠外掛來渲染。
開發自己的擴充套件程式
OK,簡單瞭解完什麼是擴充套件程式後,下面我們來看看如何開發一款擴充套件程式。
當然,首先我們要搞清楚為什麼我們需要擴充套件程式,它有什麼作用呢?
就我而言,最近我開發了一款簡單的擴充套件程式 —— URLHelper 。你可以在 chrome 應用商店下載到它:
開發它的原因是因為,在我們的業務開發中,開發過程經常需要面對超長的 URL,帶有 N 多個引數,它可能長這樣:
1 |
http://tv.video.qq.com/xxx/xxx/xxx/index?rootdomain=test.tv.video.qq.com&guid=066de07bdd33422f95b7ddaf993b2004&tvid=0930DCE900E081E142ED006B56025BA7&appver=3.1.0&bid=31001&appid=101161688&vipbid=38&fromvipbid=38&cid=qk97pyegxz8kdug&vid=&pid=&mid=&from=501&qua_info=PT%3DSNMAPP%26CHID%3D10009%26VN%3D3.1.0%26PR%3DVIDEO%26TVKPlatform%3D670603%26SMARKET%3D&type=0&listid=&matchid=&channelid=&source1=747&source2=709&penid=D21D81E4489E43422F842235B52DD&access=82E8E64DDD4A531B6FFA3E0967F76&kt_login=qq&vuserid=&vusession=&oauth_consumer_key=101161688&kt_userid=924400965&kt_license_account=SNM_0059858531&main_login=qq&kt_login_support=qq%2Cwx%2Cph&kt_boss_channel=tx_snm&ott_flag=2&sop=9&actid=&tvactid=&tv_params=policy_id%3D88&disable_update=&dp=&du=&viewid=&dv=&pageid=&ptag=&redirect_url=http%3A%2F%2Ftest.tv.video.qq.com%2Fktweb%2Fpay%2Fphone%2Fscan%3Frootdomain%3Dtest.tv.video.qq.com%26guid%3D066de07bdd33422f95b7ddaf993b2004%26tvid%3D0930DCE900E081E142ED006B56025BA7%26appver%3D3.1.0%26bid%3D31001%26appid%3D101161688%26vipbid%3D38%26fromvipbid%3D38%26cid%3Dqk97pyegxz8kdug%26vid%3D%26pid%3D%26mid%3D%26from%3D501%26qua_info%3DPT%253DSNMAPP%2526CHID%253D10009%2526VN%253D3.1.0%2526PR%253DVIDEO%2526TVKPlatform%253D670603%2526SMARKET%253D%26type%3D0%26listid%3D%26matchid%3D%26channelid%3D%26source1%3D747%26source2%3D709%26openid%3DD21D81E44801E9E43422F842235B52DD%26access_token%3D82E8E64DDD4EDA531B6FFA3E09676F76%26kt_login%3Dqq%26vuserid%3D%26vusession%3D%26oauth_consumer_key%3D101161688%26kt_userid%3D924400965%26kt_license_account%3DSNM_0059858531%26main_login%3Dqq%26kt_login_support%3Dqq%252Cwx%252Cph%26kt_boss_channel%3Dtx_snm%26ott_flag%3D2%26sop%3D9%26actid%3D%26tvactid%3D%26tv_params%3Dpolicy_id%253D88%26disable_update%3D%26dp%3D%26du%3D%26viewid%3D%26dv%3D%26pageid%3D%26ptag%3D%26opres%3D0&%24from=201 |
因為除錯的需要,經常要找到某一個特定的引數,獲取或者修改它的值。
讀者可以嘗試一下,貼到瀏覽器中,找到 cid 引數,修改為另外一個值。如果沒有工具,這個過程是很痛苦的。一次還好,如果一天重複這個動作幾十次,就有必要考慮藉助工具了。
基於這個出發點,我製作了 URLHelper 這個擴充套件,它的介面大概長這個樣子,可以非常方便的對 URL 引數進行刪查改排序,修改引數重新整理頁面:
所以,擴充套件程式我覺得每個前端都可以開發,用於解決我們工作生活中在使用瀏覽器遇到的各種問題,譬如有名的 :
- WEB 前端助手 提供的字串編碼、JSON 格式化
- PageSpeed 提供的頁面效能檢測等等
- 二維碼生成器 將 URL 轉化成對應的二維碼
擴充套件程式架構
OK,接下來聊聊一些擴充套件程式開發相關的東西。
關於擴充套件程式的相關文件,可以看看這些文章:
首先,我覺得最重要的,是要了解整個擴充套件程式的基本架構,有幾個非常重要的檔案:
Content scripts — 內容指令碼
Content scripts 指令碼是指能夠在瀏覽器已經載入的頁面內部執行的 javascript 指令碼。可以將 content script 看作是網頁的一部分,而不是它所在的擴充套件程式的一部分。
它可以實現的一些功能的例子及適用場景,大致如下:
- 在網頁中找出未連結的 URL,並將它們轉換為超連結
- 查詢特定的資訊或者 DOM 結構,增加字型大小,使文字更具有可讀性
- 發現並處理 DOM 中的微格式資料
我們可以這樣理解它,在頁面載入完畢之後,我們的擴充套件程式會向這個頁面注入一個或者額多個指令碼,這個指令碼可以獲得瀏覽器所訪問的 web 頁面的詳細資訊。也就是我們可以利用這個指令碼收集頁面上各種我們需要的資訊。
以我上面的 URLHelper 為例子,在這個擴充套件中,content script 的作用就是拿到頁面的 URL ,然後傳遞給擴充套件程式的 background 頁面或者 popup 頁面。
當然,如果你只需要一個指令碼程式每次注入頁面後獲取頁面相關的資訊,然後上報到自己的伺服器之類的功能,這個擴充套件程式只需要這一個 Content scripts 就夠了。它不需要與其他介面或者指令碼進行互動和資訊傳遞,擴充套件幫你做的就是自動注入這個指令碼而需要你每次手動注入。
popup — 彈窗頁面
popup 頁面也非常好理解,在 manifest.json
的定義裡它是 browser_action
, 就是我們擴充套件程式的介面(彈窗頁),就是上面的那張截圖:
這個介面其實就是一個 Web 頁面,點開任意一個擴充套件頁面,右鍵都可以看到彈出檢查選項,點選這個選項,就會彈出一個開發者工具,我們就可以愉快的開始對這個頁面進行檢視 DOM 結構、檢視網路狀態、 Debug 等任意操作了:
然後:
重點,這個 popup 頁面完全由我們控制,就像一個普通的 Web 頁面,我們可以利用 Chrome 的訊息傳遞機制利用這個頁面和 Content scripts 進行互動,也就可以完成對頁面的某些控制。
以我上面的 URLHelper 為例子,在這個擴充套件中,當我點選擴充套件程式介面中的重新整理頁面按鈕的時候,會從擴充套件介面的 DOM 上將修改後引數取出拼好,並且通過 Chrome 的訊息傳遞機制 傳遞給 Content scripts,然
後 Content scripts 拿到新的引數,賦值給當前瀏覽器視窗頁面的 document.location.href
,實現頁面的重新整理。
background — 後臺網頁
除了 popup 頁面之外,還有一個 background 後臺網頁 。
chrome擴充套件程式將後臺網頁分為兩種型別:
- 持續執行的後臺網頁
- 事件頁面
是否持久存在是事件頁面與後臺網頁之間的根本區別。(剛開始使用的時候可以理解為一個東西)
應用和擴充套件程式通常需要長時間執行的指令碼來管理某些任務或狀態,這就是後臺頁面的作用。事件頁面只在需要時載入,當事件頁面不活動時就會解除安裝,以便釋放記憶體和其他系統資源,所以一般而言是推薦使用事件頁面。
它存在的目的在於,在擴充套件的整個生命週期內需要長時間管理一些任務或狀態。它的主要功能及適用場景,大致如下:
- 事件頁面監聽的某個事件觸發
- 應用或擴充套件程式第一次安裝或者更新到新版本(為了註冊事件)
- 內容指令碼或其他擴充套件程式傳送訊息
- 擴充套件程式中的其他檢視呼叫了 runtime.getBackgroundPage
以我上面的 URLHelper 為例子,在這個擴充套件中,我使用的是持續執行的後臺網頁,當瀏覽器頁面重新整理第一次注入 Content Script 時,會獲取到當前頁面 url ,然後傳送訊息並帶上 url 資訊告訴給 background 後臺網頁, background 後臺網頁收到訊息後,再轉發給 popup 頁面。
擴充套件程式小結
一個擴充套件程式最重要的我覺得就是上述的三塊內容:
- Content scripts — 內容指令碼
- popup — 彈窗頁面
- background — 後臺網頁
我們通過一個 manifest.json
的清單檔案來配置它們及一些額外資訊。關於 manifest.json
的詳細資訊,可以戳:manifest 。
接下來,我們的擴充套件要靈活地完成各種功能,最重要的就是互相間的通訊!
資訊資料在內容指令碼、彈窗頁面以及事件頁面之間傳遞是一個擴充套件程式最重要的部分。
擴充套件程式的訊息傳遞
訊息傳遞存在的必要性是因為內容指令碼在網頁而不是擴充套件程式的環境中執行,所以它們通常需要某種方式與擴充套件程式的其餘部分通訊。
擴充套件程式(彈窗頁面和後臺頁面)和內容指令碼間的通訊使用訊息傳遞的方式。兩邊均可以監聽另一邊發來的訊息,並通過同樣的通道迴應。訊息可以包含任何有效的 JSON 物件。
使用 chrome.* API
訊息傳遞,主要使用了 Chrome 瀏覽器的內建 chrome
物件進行。開啟瀏覽器,試一下,chrome 物件其實包含了非常多的功能:
各種型別的訊息傳遞都是通過這個 chrome
物件進行,分為:
- 簡單的一次性請求
- 長時間的連線
- 跨擴充套件程式訊息傳遞
- 從網頁傳送訊息
- 原生訊息通訊
當然,對於通常而言的普通擴充套件程式而言,簡單的一次性請求就足夠我們使用了,舉兩個例子。
假設我們的 manifest.json
簡單定義如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# manifest.json { "name": "Url Helper", "version": "1.0.0", "author": "Coco", "manifest_version": 2, "browser_action": { "default_popup": "popup.html" }, "background": { "scripts": ["background.js"] }, "content_scripts": [ { "js": ["contentScript.js"] } ] } |
從 Content Script 向 background 事件頁面 傳遞訊息
- Content Script ,即是注入頁面的指令碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# contentScript.js // 傳送訊息 chrome.runtime.sendMessage( { msg: '從 Content Script 向 事件頁面 傳遞訊息', result: 1 }, function(response) { if (response && response.msg) { console.log(response.msg); } } ); |
- background 後臺頁面
1 2 3 4 5 6 7 8 9 10 |
#background.js // 接收訊息 chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { if (request.result) { sendResponse({ farewell: "ok" }); } }); |
在傳送端,我們可以使用 runtime.sendMessage
或 tabs.sendMessage
方法。這些方法分別允許您從內容指令碼向擴充套件程式或者反過來傳送可通過 JSON 序列化的訊息,可選的 callback 引數允許您在需要的時候從另一邊處理迴應。
而在接收端,我們需要設定一個 runtime.onMessage
事件監聽器來處理訊息。
從 popup 彈窗頁面 向 Content Script 傳遞訊息
再舉一個翻過來的例子,從 popup 彈窗頁面 向 Content Script 傳遞訊息。
- popup 彈窗頁面
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# popup.html 頁面內引入的 popup.js let obj = { msg: '從 popup 彈窗頁面 向 Content Script 傳遞訊息', result: 0 }; // 傳送訊息 chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) { chrome.tabs.sendMessage(tabs[0].id, obj, function(response) { console.log("Send Success"); }); }); |
- Content Script
1 2 3 4 5 6 7 8 9 10 |
# contentScript.js // 接收訊息 chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) { console.log(sender.tab ? "來自內容指令碼:" + sender.tab.url : "來自擴充套件程式"); if (request && !request.result) { console.log(result.msg); } }); |
這裡有個問題需要注意,從 popup 彈窗頁面 向 Content Script 傳遞訊息時,由於瀏覽器可能同時開啟多個 tab 頁,所以需要指定一下傳遞的頁面,指定傳送至哪一個標籤頁。
使用 chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {})
則能正確選中當前開啟的標籤頁。
其他更多的訊息傳遞方式,可以戳這裡:訊息傳遞。
將擴充套件程式打包上線釋出到 Chrome 應用商店
擴充套件程式開發好了,希望供他人下載。那麼當然需要釋出到應用商店。流程大致如下:
登入到 Chrome 開發者資訊中心。
首先,你需要有一個 Google 帳號,點選這裡
,登入網上應用商店。
新增一個新項並以 zip 檔案的形式上傳檔案。
注意,要打包成 *.zip
格式,並且在根目錄下有最重要的 manifest.json
檔案,像我上傳的整個目錄結構,就非常簡單:
首次釋出,需要支付 5 美刀
選擇檔案並且成功上傳之後,下一步非常重要。第一次釋出擴充套件程式,谷歌會收取 $5 開發者註冊費用,之後可以釋出 20 個擴充套件程式 。
這裡付款中國內地的銀行卡好像都不行,只能選擇國外的 VISA 等儲蓄卡、信用卡進行支付,地區選擇美國即可。
付款完成,可以愉快的釋出了
OK,最後付款完成,就可以順利釋出了,稍等片刻,就可以搜尋到我們自己開發擴充套件程式了!
後記
其實開發一款 Chrome 擴充套件程式真的不難,而且非常有意思。感興趣但又怕麻煩的同學可以參考我這個小專案改改。Github — URL Helper
好了,本文到此結束,希望對你有幫助 :)
如果還有什麼疑問或者建議,可以多多交流,原創文章,文筆有限,才疏學淺,文中若有不正之處,萬望告知。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式