從 CoolPC Plus 學會編寫 Chrome Extension:打造一個 AI 配單助手
Chrome Extension 最迷人的地方,是它可以在不改動網站原始碼的情況下,替既有網頁補上一層新的操作體驗。這篇文章會以 coolpc-plus 這個專案為範例,拆解一個 Chrome Extension 如何在原價屋估價頁注入側邊欄、讀取頁面零件清單、呼叫 AI Provider,最後把推薦零件反映回原本的頁面。
這個專案不需要打包流程,也沒有複雜的前端框架。整體使用 Chrome Extension Manifest V3、原生 JavaScript、HTML 與 CSS 完成,因此很適合拿來理解 Chrome 插件的基本架構。
這個插件要解決什麼問題
CoolPC Plus 的目標很明確:使用者打開 原價屋線上估價 頁面後,插件會在右側加入「CoolPC AI 配單助手」側邊欄。使用者輸入預算、主要用途與補充需求後,插件會讀取頁面上已公開顯示的零件選項,整理成 prompt 交給 AI 分析,再把推薦結果顯示在側邊欄中。
更重要的是,它不是只輸出文字建議而已。AI 回覆中會帶有一段 JSON,內容包含 CoolPC 頁面上的 selectName 與 optionValue。插件解析後,會自動選取推薦零件,並在原本的估價表格上高亮標示。
整個流程可以拆成五個步驟:
- 使用
manifest.json宣告插件權限、作用頁面與注入腳本 - 使用 content script 在 CoolPC 頁面建立側邊欄 UI
- 從頁面
<select>元素擷取零件清單與價格 - 透過 background service worker 中繼呼叫外部 LLM API
- 解析 AI 回覆,將推薦零件套回頁面並高亮顯示
專案結構
專案的 README 已經整理出主要目錄。對 Chrome Extension 來說,最重要的是 manifest.json、content/、background/ 與 popup/ 這幾個部分。
1 | coolpc_explorer/ |
如果你是第一次寫 Chrome Extension,可以先把它想成三個執行環境:
content script:跑在指定網頁上,負責讀取與操作頁面 DOMbackground service worker:跑在插件背景環境中,適合處理 API 請求、事件中繼與跨來源限制popup page:點擊瀏覽器工具列上的插件圖示時出現的設定頁
CoolPC Plus 剛好把這三個角色都用到了,因此很適合當作完整範例。
第一步:用 manifest.json 定義插件入口
Chrome Extension 的入口是 manifest.json。這個檔案會告訴 Chrome:插件名稱是什麼、要在哪些頁面啟用、需要哪些權限、背景腳本在哪裡,以及點擊插件圖示時要開啟哪個 popup。
CoolPC Plus 使用的是 Manifest V3:
1 | { |
這裡有幾個關鍵設定。
permissions 中的 storage 讓插件可以使用 chrome.storage.sync 儲存設定,例如主題、AI Provider、模型、預算與 API Key。scripting 則是 Chrome Extension 常見的腳本權限。
host_permissions 決定插件可以存取哪些網域。CoolPC Plus 需要讀取 CoolPC 頁面,也需要呼叫 OpenAI、Gemini 與 Claude API,所以這些網域都必須列進來。
content_scripts 宣告了兩段腳本。第一段是主要功能,會在 CoolPC 估價頁載入 content/content.js 與 content/sidebar.css。第二段比較特別,它把 content/main-world-interceptor.js 放在 world: "MAIN" 執行,用來攔截頁面原本的 Clear() 與 FReset() 函式。
第二步:用 content script 注入側邊欄
content/content.js 是整個插件的核心。它被載入到 CoolPC 估價頁後,會建立右側 sidebar、綁定按鈕事件、讀取使用者設定,並負責後續的零件擷取與 AI 回覆處理。
在初始化階段,程式會呼叫 createSidebar():
1 | function createSidebar() { |
這段程式做了三件事。
第一,它用 document.createElement() 建立 sidebar,並將 getSidebarHTML() 產生的表單介面塞進去。第二,它額外建立一顆開關按鈕,讓使用者可以收合側邊欄。第三,它調整 document.body.style.marginRight,避免右側 sidebar 直接蓋住原本頁面內容。
這是一個很典型的 content script 寫法:不需要控制原網站的原始碼,只要在頁面載入後注入自己的 DOM 與 CSS,就能疊加新的功能。
第三步:從頁面擷取可用零件
AI 要推薦零件,前提是它必須知道頁面上有哪些選項。CoolPC Plus 沒有去抓非公開資料,而是直接讀取使用者眼前頁面中的 <select> 選單。
核心函式是 extractPartsData():
1 | function extractPartsData() { |
這裡的設計很值得學。程式不依賴後端 API,而是以目前頁面 DOM 作為資料來源。它尋找所有 name 以 n 開頭的 <select>,例如 CPU、主機板、記憶體、SSD、顯示卡等分類,再逐一讀取其中的 <option>。
每個 option 會被整理成三個欄位:
value:CoolPC 頁面中該選項的值text:使用者看到的零件名稱與描述price:從文字中解析出來的價格
後續 AI 回覆時,只要提供同一組 selectName 與 optionValue,插件就可以把推薦結果對應回頁面上的實際選項。
第四步:建立穩定的 AI Prompt
很多 AI 功能失敗的原因,不是模型不會回答,而是程式沒有給它足夠明確的輸出格式。CoolPC Plus 在 content script 裡定義了固定的 system prompt,要求 AI 必須用繁體中文回答,並且最後只能輸出一段 JSON code block。
專案要求 AI 回覆包含這些區塊:
- 配置摘要
- 推薦配置
- 選擇理由
- 注意事項
- 最後一段 JSON 結構,用於自動高亮頁面上的推薦零件
JSON 格式大致如下:
1 | { |
這個設計讓 AI 回覆同時具備「給人閱讀」與「給程式解析」兩種用途。Markdown 文字可以顯示在 sidebar,而 JSON 則交給程式做後續自動化操作。
在建立 user prompt 時,程式會把使用者需求與可選零件清單一起組合起來:
1 | const userPrompt = `[使用者需求] |
這裡還有一個實用細節:程式會先依預算過濾過高價格的單品,並且每個分類最多取前 100 筆。這樣可以避免 prompt 過長,也能降低 AI 推薦完全不符合預算的機率。
第五步:用 background service worker 呼叫外部 API
content script 雖然可以操作頁面 DOM,但直接呼叫外部 API 時容易遇到 CORS 與權限問題。因此 CoolPC Plus 把 OpenAI、Gemini 與 Claude 的 API 呼叫集中放在 background/service-worker.js。
content script 會用 chrome.runtime.sendMessage() 傳送請求:
1 | const response = await chrome.runtime.sendMessage({ |
background service worker 收到後,依照 provider 分派到不同函式:
1 | chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { |
return true 是這段程式的關鍵。Chrome 的 message listener 預設是同步回應,如果要在非同步 API 請求完成後才呼叫 sendResponse(),就必須回傳 true,讓 message channel 保持開啟。
這也是 Manifest V3 很常見的架構:content script 專心處理頁面,background service worker 專心處理外部服務與插件層級的工作。
第六步:支援 Chrome 內建 AI
除了外部 API,CoolPC Plus 也支援 Chrome 內建 AI,也就是 Gemini Nano。這種模式不需要 API Key,但需要使用者的瀏覽器版本與實驗功能支援。
專案在 content script 中直接檢查可用 API:
1 | const api = self.LanguageModel ?? window.LanguageModel ?? self.ai?.languageModel ?? window.ai?.languageModel ?? null; |
這段寫法同時相容 Chrome 136+ 的 LanguageModel,以及 Chrome 127 到 135 的 window.ai.languageModel。如果 API 不存在,程式會提示使用者確認 Chrome 版本與 flags 設定。
若 API 可用,插件會建立 session,送出 prompt,最後記得銷毀 session:
1 | const session = await api.create({ systemPrompt }); |
這裡的好處是可以保留同一套 UI 與 prompt 流程,只是在 provider 選擇 chrome-ai 時改走本機模型。
第七步:解析 AI 回覆並高亮頁面
AI 回覆完成後,processLLMResponse() 會先找出最後的 JSON code block:
1 | const jsonMatch = rawContent.match(/```json\s*([\s\S]*?)```/); |
接著程式會移除 JSON,只把 Markdown 內容顯示在 sidebar:
1 | const textContent = rawContent.replace(/```json[\s\S]*?```/g, '').trim(); |
如果 JSON 中有推薦項目,插件會呼叫 applyRecommendedParts() 與 showRecommendationHighlights()。前者負責真的選取 <select>,後者負責視覺標示。
1 | function applyRecommendedParts(recommendations) { |
這裡一定要觸發 change 事件,因為 CoolPC 原頁面可能會在選項改變時重新計價。如果只改 select.value,畫面看起來選到了,但原網站自己的計算邏輯未必會同步執行。
第八步:處理頁面原本的重置行為
CoolPC 頁面本身有清除與重置功能。當使用者執行這些操作時,插件也應該清掉自己的高亮狀態,否則頁面資料已經重置,AI 標記卻還留在畫面上,體驗會很混亂。
這就是 content/main-world-interceptor.js 的用途。它在 main world 執行,包住頁面原本的 Clear() 與 FReset():
1 | (function () { |
content script 再監聽這個事件:
1 | document.addEventListener('ai-advisor-clear', clearHighlights); |
這個做法很漂亮,因為 content script 預設跑在 isolated world,和頁面自己的 JavaScript 執行環境不同。若要攔截頁面上的全域函式,就需要透過 world: "MAIN" 的腳本進入頁面主世界,再用 CustomEvent 通知 isolated world 的 content script。
第九步:用 popup 儲存設定
Chrome Extension 常見的另一個入口是 popup。CoolPC Plus 的 popup/index.html 與 popup/popup.js 提供設定介面,讓使用者選擇主題、AI Provider、模型與 API Key。
設定會被存在 chrome.storage.sync:
1 | chrome.storage.sync.set({ [STORAGE_KEY]: settings }, () => { |
content script 載入 sidebar 時,也會從同一個 STORAGE_KEY 讀取設定。因此 popup 和 sidebar 可以共享狀態,使用者在 popup 改了 provider 或主題,回到 CoolPC 頁面時就能同步套用。
這裡也有一個安全與體驗上的取捨。專案提供「記住 API Key」選項;如果使用者勾選,API Key 會寫入瀏覽器同步儲存空間。如果不想保存,就取消勾選,插件只在當下使用輸入值。
第十步:本機載入與測試插件
CoolPC Plus 目前不需要額外 build step,因此開發流程非常直接。
- 下載或 clone 專案
- 開啟 Chrome 的
chrome://extensions/ - 開啟右上角「開發人員模式」
- 點選「載入未封裝項目」
- 選擇專案資料夾
- 前往
https://www.coolpc.com.tw/evaluate.php - 在右側 sidebar 輸入預算、用途與補充說明
- 選擇 AI Provider、模型與 API Key
- 點選「分析並推薦零件」
修改程式後,只要回到 chrome://extensions/ 重新載入擴充功能,再刷新 CoolPC 頁面即可看到變更。
專案也提供幾個簡單的語法檢查指令:
1 | node --check content/content.js |
因為這個專案沒有打包器與型別檢查,node --check 至少可以先確認 JavaScript 語法沒有錯。git diff --check 則可以檢查是否有多餘空白或格式問題。
從這個專案可以學到什麼
CoolPC Plus 雖然是一個具體情境的工具,但它涵蓋了 Chrome Extension 開發中非常實用的幾個觀念。
第一,manifest.json 是插件的控制中心。要在哪個網頁啟用、要讀取哪些外部網域、要載入哪些 content scripts,都必須在這裡說清楚。
第二,content script 很適合做「頁面增強」。它可以注入 DOM、讀取表單、改變樣式,也能把頁面上的既有資料整理成自己的應用資料。
第三,background service worker 適合當中繼層。當功能需要呼叫外部 API、處理權限或封裝共用邏輯時,把它放在 background 會比全部塞在 content script 更清楚。
第四,AI 功能要能落地,不能只依賴自然語言。CoolPC Plus 用 Markdown 給使用者閱讀,再用 JSON 給程式解析,這種「文字說明 + 結構化資料」的輸出設計,是很多 AI 工具都可以參考的模式。
第五,寫插件時要尊重原網站的狀態。像是選取零件後觸發 change 事件、頁面重置時同步清掉高亮,這些細節都會直接影響使用者是否覺得工具可靠。
結語
如果你想學 Chrome Extension,CoolPC Plus 是一個很好的實戰範例。它沒有過重的技術棧,卻完整示範了 Manifest V3、content script、background service worker、popup、chrome.storage.sync、跨來源 API 呼叫與頁面 DOM 操作。
更重要的是,這個專案不是為了展示插件 API 而寫的玩具範例,而是從真實使用情境出發:使用者在估價頁上挑零件,插件就在同一個頁面補上 AI 分析、推薦與高亮。這也是 Chrome Extension 最有價值的地方:它能在既有網頁流程中,補上一個剛好需要的輔助層。