葉子 已發佈 2019-10-18

寫給前端的 Chrome extension 教學

chrome extension 是什麼?

chrome extension 也就是在 chrome 瀏覽器中的擴充功能,透過擴充功能 / 插件可以讓我們在使用瀏覽器時獲得某些資訊或是進行某些操作。聽起來有點抽象,來實際說明幾個例子!
之前有在 IT 邦幫忙推薦過十個好用的 chrome 插件,傳送門底加:
https://ithelp.ithome.com.tw/articles/10204029
https://ithelp.ithome.com.tw/articles/10204351
以文章提到的 Wappalyzer 來說,透過這個插件就可以取得這個網站所使用到的技術或是插件等等;而以 JSON Viewer 來說,則是可以將資料進行格式化。

總之,這些插件都是掛載在瀏覽器以方便我們進行一些行為,由於 extension 可以在指定網頁中加入額外的內容,所以對於前端來說也是很適合學習且易上手,學會後也可以做各種的運用啦~

如同在公司有「工具人」之稱的我,為加速工作流程也做過幾個 extension,也因為對 extension 有基礎的了解,而使用插件來輔助搶周興哲演唱會的門票(真的有搶到!!

話不多說,接下來馬上就開始介紹如何自己製作一個插件吧!

extension 架構簡介

extension 是由 manifest.json 以及其他網頁檔案組成的
主要架構:

  • Manifest
  • Background Script
  • UI Elements
  • Content Script
  • Options Page

manifest.json

每個 extension 都要有一個 JSON 格式的清單文件,用來提供重要的資訊。

這邊舉例說明:

{
// 必填
"manifest_version": 2,
"name": "ticket extension",
"version": "1",

// 建議
"description": "搶票輔助",

// 擇一(browser_action / page_action )或不填
"browser_action": {
  "default_icon": "img/tzu.png",
  "default_title": "搶票輔助"
},
"background": {
  "scripts": [
    "background.js" 
  ]
},
// 選填
"options_page": "options.html",
"permissions": [ "activeTab", "storage" ],
"content_scripts" : [
{
  "matches" : [ "https://tixcraft.com/ticket/ticket/*" ],
  "run_at": "document_end",
  "js" : [ "jquery.min.js", "js/ticket.js" ]
},
{
  "matches" : [ "https://tixcraft.com/ticket/area/*" ],
  "run_at": "document_end",
  "js" : [ "jquery.min.js", "js/area.js" ]
},
{
  "matches" : [ "https://tixcraft.com/*" ],
  "run_at": "document_end",
  "css": ["css/all.css"],
  "js" : ["jquery.min.js", "js/detail.js" ]
}
]
}

想了解所有的項目設定清單請看:https://developer.chrome.com/extensions/manifest

Background Script

Background Script 可以用來對 extension 做事件的監聽,會在觸發事件之後才執行。它僅在需要時才加載。

UI Elements

可在 extension 上加上 UI 元素,大多 extension 都會設定 browser action 或是 page action。

兩者的差異:

image alt

image alt

image alt

更多細節設定:https://developer.chrome.com/extensions/user_interface

Content Script

可以用來讀取或是寫入網頁的 DOM。

另外,也可以運用 Chrome API 來做更多的行為。例如:storage (儲存資料用)
先附上 Chrome API 文件介紹

以上三者的關係圖:
image alt

Options Page

可以藉由 Options Page 提供客製化的擴充功能。
Options Page 可用從右鍵 > 選項開啟新 tab 來打開頁面
也可以透過設定讓 Options Page 用嵌入式的框框打開

新 tab 打開頁面

嵌入式的框框

圖片皆來自 chrome extension 官方文件

以上為 chrome extension 的基礎架構,有個概念之後,接下來會進入實作的介紹並一一運用以上提到的架構內容~

實作

這邊以搶票輔助的插件來做介紹:

使用的情境

由於演唱會門票總是秒殺,手速再快都只能看到售完!
因此想透過插件省去需要點擊與填寫的步驟,在取到網址時直接完成前面步驟到輸入驗證碼的區塊(還無法透過程式判斷 & 自動填寫驗證碼 QAQ)
不過也是省了中間的程序,手速處理驗證碼就可以了 XD

以流程來區分為幾個項目做介紹,主要會介紹在此項目中用了哪些插件相關功能:

  1. 設定日期、購買票數、票價區域選擇的設定介面
  2. 在節目售票頁面可觀看到目前設定好的項目並觸發搶票
  3. 跳轉後會進入選位子的區域,預設會以票價區域選擇取得對應的 url 進行跳轉
  4. 進入購票頁面後會自動帶好購買票數與勾選同意條款,並 focus 到驗證碼的 input

1. 設定日期、購買票數、票價區域選擇的設定介面

第一個項目會使用到的有 Background Script, UI Elemtents, Options page, Chrome API

首先,extension 的縮圖(如下圖)就是透過上述提過的 UI Elemtents 中的 browser_action 來設定。

在 manifest.json 寫入設定,icon 的部分就使用一般 png 的圖檔,並寫上對應的路徑

"browser_action": {
  "default_icon": "img/tzu.png",
  "default_title": "搶票輔助"
},

再來是日期、購買票數、票價區域選擇的設定介面,使用 Options page 設定另開頁面的方式來做。

在專案中加入 option.html 並在 manifest.json 的設定

"options_page": "options.html",

此時在 extension 按下右鍵 > 選項,就可以開啟 option.html
image alt

option.html 中就和一般網頁寫的 HTML 檔案一樣,我這邊是用 Bootstrap 設定樣式與把需要的欄位加上,並在最後引入 option.js。而在 option.js 中透過 Chrome API 來儲存項目。
舉例來說:
在 option.html

<div class="form-group">
  <label for="ProgramDate">節目日期 :</label>
  <input type="date" id="ProgramDate" class="form-control">
</div>
<button id="save" type="button" class="btn btn-info">儲存設定</button>

option.js

// 綁定按鈕監聽
document.getElementById('save').addEventListener('click', save_options);
// save_options 函式中取得 input 值,並用 chrome.strage.local.set 來儲存
function save_options() {
var ProgramDate = document.getElementById('ProgramDate').value;
chrome.storage.local.set({
    'ProgramDate': ProgramDate
    }, function() {
        // 完成後要做的事
    });
}

在使用 Chrome API 要注意:

  1. 在 manifest.json 要多加上設定,因為我們是要使用 storage,所以在 permissions 就加上 storage。
    "permissions": [ "activeTab", "storage" ],
  2. chrome.storage 會分為 storage.sync 和 storage.local, storage.sync 會讓數據保存到 google 帳號。
    3.chrome.storage.local.set 的資料是物件的類型,例如:
    {
     'key', value,
     'ProgramDate': ProgramDate
    }

設定好後,因為要開啟 option.html 只能按右鍵 > 選項實在麻煩,所以我們可以透過 Chrome API 來做點擊 extension icon 就打開 option 頁面

這邊需要一個 background.js 來做 Background Script 的設定
因此首先先建立 background.js,再使用 chrome.browserAction.onClicked 監聽事件,當 click 的時候就新開 tabs,並導到 option.html 頁面

chrome.browserAction.onClicked.addListener(tab => {
  chrome.tabs.create({
    url: chrome.extension.getURL("options.html")
  })
})

在 manifest.json

"background": {
  "scripts": [
    "background.js" 
  ]
},

2. 在節目售票頁面可觀看到目前設定好的項目並觸發搶票

使用到的有 Content Script, Chrome API

Content Script 用意是在頁面上加入一個寫入一個小區塊並顯示前面設定好的資料和開始取得網頁元素的按鈕。

  1. 新增一個 detail.js
    可用 append 的方式把 html 插入到網頁頁面中,也就是和一般 JS 語法將 html 標籤加入到頁面是一樣的意思,樣式的部分同樣也可以透過 css 設定,再透過 manifest.json 將這個 css 引入。

舉例:

$('body').append(`<div class="h_popup_outbox">
...省略
</div>`);

這樣就可以在視窗上看到如同這樣的畫面

manifest.json 中將需要的檔案加入,透過 matches 可以讓網頁是在這個網址下才取得 css 和 js 檔案。

{
  "matches" : [ "https://tixcraft.com/*" ],
  "run_at": "document_end",
  "css": ["css/all.css"],
  "js" : ["jquery.min.js", "js/detail.js" ]
}

如同上圖中看到,點選『開始搶票』就會觸發函式去抓取售票網頁上的『立即購票』DOM 元素,這邊的抓取 DOM 元素就使用 $('className') 的方式即可~

若是觸發後有取得 response 則比對設定的日期 (用 Chrome API 處理,下一個項目再說明),相同則跳轉到取得的 data-href。這一段主要也是 Content Script 做的事情(讀取、寫入網頁 DOM)

3. 跳轉後會進入選位子的區域,預設會以票價區域選擇取得對應的 url 進行跳轉

這邊一樣是使用到 Content Script, Chrome API

Content Script 因為要針對這頁來抓取座位區域的對應,所以這邊在這個網址下又會新增一個 js 檔案。
在 manifest.json 設定更細緻的 matches 就可以了~

{
  "matches" : [ "https://tixcraft.com/ticket/area/*" ],
  "run_at": "document_end",
  "js" : [ "jquery.min.js", "js/area.js" ]
},

而第一步設定好的那些內容,就是使用 chrome.storage.local.get,例如:

chrome.storage.local.get(['ProgramSit', 'eventId'], items => {
  choosed_sit = `${items.eventId}_${items.ProgramSit}`;
});

chrome.storage.local.get 後面是接上陣列資料,陣列裡則是要取出來的 key 值。

4. 進入購票頁面後會自動帶好購買票數與勾選同意條款,並 focus 到驗證碼的 input

最後一個流程使用到的就和 2,3 項目相同,都是透過 chrome api GET 設定好的參數,並取得網頁上的 DOM 元素寫入資料。到這一步將驗證碼填好後按下 enter 就送出了!

實作小結

雖然以上說明看起來是落落長,但實際上使用到的技巧到大同小異,了解了插件的結構以及具備前端的基礎技能(HTML, CSS, JavaScript)就能開發出屬於自己的工具了!

因為目前我所開發過的類型都是偏向簡化網頁上的操作行為,所以在開發插件的時候,首先會先確定好這個插件所要完成的目標為何,並開始設計流程與觀察點擊後觸發的行為。最後再對應回去需要的架構與技巧~

完整程式碼

為了達成簡化網頁上的操作行為,這邊一定要補充一個我常用的技巧!!

補充:實用小技巧 - Postman Interceptor

這是一個 Postman 的插件,在網頁上開啟它後,它可以取得在網頁的行為,因此當你想了解這個按鈕點下後是 GET 哪支 API 或是 POST 什麼資料出去、需要帶哪些參數,通通告訴你!!
插件連結
安裝好後,點一下

接著就可以在 Postman 中的 history 看到這些行為

插件好處

  1. 因為是掛在網站下執行,所以 call api 時可以避免掉 cors 的問題
  2. 直接操作網站 DOM 元素,可以將操作介面流程自動化

extension 上架

做完插件後,除了可以供給自己使用,也可以透過上架的方式,讓 extension 上到商店提供給其他人下載
流程上也非常簡單,只要有 google 帳號,登入開發者頁面後,就可以選擇上傳檔案來上架。

上架需要 5 美金,付完之後就可以無限上架插件,只需要付費一次哦!
上架之後也會由 google 進行審核,通過後就可以提供給大家安裝使用囉

流程的部分官方寫得蠻清楚的,附上連結提供參考

總結

extension 的開發有蠻大一部分都與前端所需技能相符,因此有興趣的夥伴們也可以嘗試製作自己的插件看看,希望透過這篇文章帶大家認識 chrome extension,若是有開發出好玩的 extension 也歡迎大家跟我分享!

參考資料

https://developer.chrome.com/extensions
https://ithelp.ithome.com.tw/users/20079450/ironman/1149
https://github.com/dsync5566/tixCraftSupport

關於筆者

暱稱:葉子

介紹:我的部落格:https://tzuhui.github.io/ 歡迎參觀指教 :D

文章列表 文章列表