# Chrome Extension https://www.udemy.com/course/chrome-extension-development-course-for-everyone/ 線上課程的筆記和心得整理 ## 包含4個部分 1. Manifest file 該應用程式的資訊,用於顯示於chrome商店和使用者 2. background scripts 執行background屬性內的js,通常是監聽使用者的一些行為並執行特定函式,例如新增書籤時 3. content scripts 執行content屬性內的js,同時也會有matches屬性規定在哪個網址內才執行 4. UI elements 跟使用者互動的元素,例如套件的顯示logo、滑鼠移過去hover的字樣、或點下顯示一個小的html(可以包含一些資訊或按鈕) # Manifest file ## 創建一個chrome extension node安裝套件 `npm install type @types/chrome` 建立manifest.json ```json= { "name": "my first extension", "version": "1.0.0", "description": "description", "manifest_version": 2 } ``` 這邊只填寫必要的屬性,想知道更多manifest的屬性可以參考:https://developer.chrome.com/extensions/manifest chrome網址輸入 `chrome://extensions/` 右上角開啟`開發人員模式` 點擊`載入未封裝項目`並選擇該專案資料夾 ![](https://i.imgur.com/ARcce5m.jpg) # background scripts manifest.json新增background屬性 ```json= { "name": "my first extension", "version": "1.0.0", "description": "description", "manifest_version": 2, "background": { "scripts": ["background.js"], "persistent": false // 如果要隨時接收chrome或WebAPI等情況才會永遠執行 } } ``` 新增background.js ```javascript= // extension載入完畢時執行 chrome.runtime.onInstalled.addListener(()=>{ console.log('installed') }) ``` 都儲存後直接到`chrome://extensions/`點擊右下角的重新載入就好了 ![](https://i.imgur.com/5z06Km5.jpg) 然後點擊背景頁面查看執行成果 ![](https://i.imgur.com/SlCt8YW.jpg) 接著繼續新增 ```javascript= // extension載入完畢時執行 chrome.runtime.onInstalled.addListener(()=>{ console.log('installed') }) // 新增頁籤時執行 chrome.bookmarks.onCreated.addListener(()=>{ alert('Bookmark saved') }) ``` 然後同樣儲存後重新載入 ![](https://i.imgur.com/NV8ZOvt.jpg) 當有錯誤時可以點擊錯誤查看問題 ![](https://i.imgur.com/kvQ97WT.jpg) 這個錯誤是因為bookmarks必須要有權限才行,所以回到manifest.json新增permissions屬性 ```json= { "name": "my first extension", "version": "1.0.0", "description": "description", "manifest_version": 2, "background": { "scripts": ["background.js"], "persistent": false // 如果要隨時接收chrome或WebAPI等情況才會永遠執行 }, "permissions": [ "bookmarks" ] } ``` 清除原本的錯誤訊息並重新載入後,如果沒有再跳出錯誤的話就代表成功了 當你嘗試加入書籤時就會跳出alert的視窗 ![](https://i.imgur.com/YQWBl1X.jpg) # content scripts manifest.json新增content_scripts屬性 ```json= { "name": "my first extension", "version": "1.0.0", "description": "description", "manifest_version": 2, "background": { "scripts": ["background.js"], "persistent": false // 如果要隨時接收chrome或WebAPI等情況才會永遠執行 }, "permissions": [ "bookmarks" ], "content_scripts": [ { "js": ["content.js"], // 在那些網址會載入content.js "matches": ["https://*.youtube.com/*"], // 除了哪些網址之外 "exclude_matches": ["https://*.youtube.com/watch*"] } ] } ``` 新增content.js ```javascript= window.onload = () => { document.querySelector('#end').prepend('Dark mode') } ``` 儲存並重新載入之後連到youtube首頁 ![](https://i.imgur.com/WatyhAQ.jpg) 會發現左邊多了一個Dark mode的字樣, 而隨便點進去一個影片後重新整理(注意因為沒有監控url的變化,所以一定要重新整理),就會發現上面的Dark mode字樣不見了 將Dark mode文字變成按鈕 ```javascript= // content.js window.onload = () => { const button = document.createElement('button') button.id = "darkModeButton" button.textContent = "DO IT DARK" document.querySelector('#end').prepend(button) button.addEventListener('click', () => enableDarkMode()) } function enableDarkMode() { document.querySelector('ytd-app').style.background = 'black' } ``` 儲存並重新載入後 ![](https://i.imgur.com/ZFfyTyl.jpg) 按下button背景就會變成黑色了 另外可以在manifest.json新增run_at屬性,決定何時執行 ```json= { "name": "my first extension", "version": "1.0.0", "description": "description", "manifest_version": 2, "background": { "scripts": ["background.js"], "persistent": false }, "permissions": [ "bookmarks" ], "content_scripts": [ { "js": ["content.js"], // 在那些網址會載入content.js "matches": ["https://*.youtube.com/*"], // 除了哪些網址之外 "exclude_matches": ["https://*.youtube.com/watch*"], "run_at": "document_end" } ] } ``` # UI elements 新增icons, browser_action屬性 ```json= { "name": "my first extension", "version": "1.0.0", "description": "description", "manifest_version": 2, "background": { "scripts": ["background.js"], "persistent": false }, "permissions": [ "bookmarks" ], "content_scripts": [ { "js": ["content.js"], "matches": ["https://*.youtube.com/*"], "exclude_matches": ["https://*.youtube.com/watch*"], "run_at": "document_end" } ], "icons": { "16": "youtube_icon.png", "48": "youtube_icon.png", "128": "youtube_icon.png" }, "browser_action": { "default_title": "Created by lovebuizel, enjoy!", "default_popup": "popup.html" } } ``` 新增popup.html ```htmlmixed= <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <img src="./youtube_icon.png" alt=""> <p>Hello</p> 注意a連結一定要target="_blank"才有效 <a href="https://google.com" target="_blank"> <button>Visit homepage</button> </a> </body> </html> ``` 點擊extension時會顯示`popup.html` ![](https://i.imgur.com/aImJ7fE.jpg) 滑鼠移過去時 ![](https://i.imgur.com/NHSeAU3.png) youtube icon來源:https://www.youtube.com/intl/zh-TW/yt/about/brand-resources/#logos-icons-colors # 使用storage儲存資料 permissions增加storage權限 ```json= { "name": "my first extension", "version": "1.0.0", "description": "description", "manifest_version": 2, "background": { "scripts": ["background.js"], "persistent": false }, "permissions": [ "bookmarks", "storage" ], "content_scripts": [ { "js": ["content.js"], "matches": ["https://*.youtube.com/*"], "exclude_matches": ["https://*.youtube.com/watch*"], "run_at": "document_end" } ], "icons": { "16": "youtube_icon.png", "48": "youtube_icon.png", "128": "youtube_icon.png" }, "browser_action": { "default_title": "Created by lovebuizel, enjoy!", "default_popup": "popup.html" } } ``` chrome提供的storage api有兩種 * local storage 就是一般web所熟知的local storage,限定同個裝置 * sync storage chrome如果有登入google帳號並且啟動同步功能的話,裝置不同也能存取之前的資料 以下範例使用`local storage` 新增checkbox讓使用者下次造訪時自動使用上次儲存的紀錄 ```javascript= // content.js window.onload = () => { const button = document.createElement('button') button.id = "darkModeButton" button.textContent = "DO IT DARK" const input = document.createElement('input') input.type = 'checkbox' input.id = 'darkSetting' document.querySelector('#end').prepend(button, input, 'Auto apply?') button.addEventListener('click', () => enableDarkMode()) input.addEventListener('click', () => storeSetting()) checkSetting() } function checkSetting() { chrome.storage.local.get(['enabled'], (result) => { const isEnabled = result.enabled console.log(isEnabled) document.querySelector('#darkSetting').checked = isEnabled if(isEnabled) { enableDarkMode() } }) } function storeSetting() { const isEnabled = document.querySelector('#darkSetting').checked const setting = { enabled: isEnabled } // 使用sync storage的話則用chrome.storage.sync chrome.storage.local.set(setting, () => { console.log('stored', setting) }) } function enableDarkMode() { document.querySelector('ytd-app').style.background = 'black' } ``` # 上傳到chrome線上應用程式商店 https://chrome.google.com/webstore/category/extensions?hl=zh-TW 將node_modules資料夾、package.json、package-lock.json以外的檔案壓縮成zip檔(一定要zip檔才行,而不是rar等其他壓縮檔)上傳 發佈前必須繳一次性的註冊費(5塊美金),繳過一次後就不用再繳了,最多可以發佈20個商品。