寫個自己的 chrome 插件

有沒有好奇 chrome[1] 插件是用什麼做的?像類似掘金插件又是怎麼實現的,當我安裝稀土掘金插件後,我的導航頁都被改掉了,因此你也可以做一個類似的插件,來導航你公司的一些產品,方便快捷的實現你的內部導航

在開始本文之前,主要是從零認識一個chrome插件, 主要會從以下幾點去認識chrome插件

正文開始...

首先預知的幾個文件

manifest.json,必須在插件根目錄上新建一個這樣的文件, 我們從官網查看更多的 manifest[2] 信息

{
    // 必不可少
    "manifest_version": 3, // 擴展插件版本必須是2以上
    "name": "Maic_test_chrome", // 擴展名稱
    "description": "lesson demo", // 擴展描述
    "version": "1.0",
    // 可選
    "action": {
        "default_popup": "popup/index.html", // 默認的頁面
        "default_icon": "logo.png" // 瀏覽器擴展插件顯示圖標
    },
    // 在插件列表裏顯示不同尺寸的圖標
    "icons": {
        "16": "images/icon-16.png",
        "32": "images/icon-32.png",
        "48": "images/icon-48.png",
        "128": "images/icon-128.png"
    }
}

讓當前網頁加載一個腳本

content_scripts指定加載對應腳本js,css注意matches中匹配的是當前訪問的 url, 當選擇<all_urls>時,匹配任何 url, 必須要有 matches[3] 否則不會生效

 "content_scripts": [
        {
            "js": [
                "scripts/content.js"
            ],
            "matches": [
                "https://*.wmcweb.cn/*",
                "<all_urls>"
            ]
        }
    ]

background 增強瀏覽器事件程序的 js

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

background.jscontent.js通信

background.js在插件頁面加載,background.js調用onMessage.addListener接收content.js發送過來的數據

function callback(info, curent, sendToContent) {


}
chrome.runtime.onMessage.addListener(callback)
// background.js 在插件頁面加載
const user = {
    username: 'Maic'
};
// 調用onMessage.addListenter
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    console.log('background.js', message, sender)
    // 2. A page requested user data, respond with a copy of `user`
    if (message === 'get-user-data') {
        sendResponse(user);
    }
});

content.js在你指定的匹配域名頁面加載,與當前瀏覽器加載的頁面同環境

content.jscontentbackground.js發送信息

chrome.runtime.sendMessage(info, callbackResponse)
// sendMessage content.js
chrome.runtime.sendMessage('get-user-data', (response) => {
    console.log('received user data', response);
});

popup.jscontent.js通信

popup頁面需要查找當前激活的tabs

// popup.js
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        chrome.tabs.sendMessage(tabs[0].id, {}, function (response) {
            console.log(response, 'content.js回傳過來的信息');
   });
});

content.js接收信息

function callback(request, sender, sendResponse) {}
chrome.runtime.onMessage.addListener(callback)

content.js詳細代碼參考以下

// content.js
console.log('loader-content')
// 1. content向service worker發送信息
chrome.runtime.sendMessage('get-user-data', (response) => {
    // 2,接受service worker回調過來的信息
    console.log('received service worker data', response);
});


const render = ({ style, title }) => {
    const boxDom = document.querySelector('.box');
    const contentDom = document.querySelector('.content');
    const resultDom = document.querySelector('.result');
    boxDom.style.width = style.width;
    boxDom.style.height = style.height;
    boxDom.style.backgroundColor = style.backgroundColor;
    contentDom.innerText = title;
    resultDom.innerText = JSON.stringify({ ...style, title }, null, 2)
}
// 接收popup.js發送過來的信息
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
    console.log('content', request, sender);
    const {
        inputColorValue,
        titleValue,
        widthValue,
        heightValue } = request;
    const style = {
        width: `${widthValue}px`,
        height: `${heightValue}px`,
        backgroundColor: inputColorValue
    }
    const receivePopupInfo = {
        style,
        title: titleValue
    }
    // 向popup.js回傳信息
    sendResponse(receivePopupInfo)
    render(receivePopupInfo)
});

background.js參考如下

const user = {
    username: 'Web技術學苑'
};
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    console.log('background.js', message, sender)
    if (message === 'get-user-data') {
        sendResponse(user);
    }
});

popup.js參考如下

const $ = id => document.getElementById(id);
function setBadge() {
    const inputColorValue = $('color-input').value;
    const titleValue = $('title-input').value;
    const widthValue = $('width-input').value;
    const heightValue = $('height-input').value;
    const info = {
        inputColorValue,
        titleValue,
        widthValue,
        heightValue
    }
    chrome.action.setBadgeText({ text: inputColorValue });
    // 擴展腳本向content發出信息
    chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
        console.log(tabs)
        chrome.tabs.sendMessage(tabs[0].id, info, function (response) {
            console.log(response, 'content.js回傳過來的信息');
        });
    });
}


$('submit').addEventListener('click', setBadge);
['width', 'height'].forEach(dom => {
    const curent = $(`${dom}-input`);
    curent.addEventListener('change', (evt) => {
        $(`${dom}-result`).innerText = evt.target.value;
    })
});

我們再看下popup.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta  />
    <title>Document</title>
    <link rel="stylesheet" href="popup.css" />
  </head>
  <body>
    <div>
      <div>title: <input type="text" value="我是標題" /></div>
      <div>color:<input type="color" /></div>
      <div>
        width: <input type="range" value="30" max="1000" />
        <span>30</span>
      </div>
      <div>
        height: <input type="range" value="30" max="1000" />
        <span>30</span>
      </div>
      <button>確定</button>
    </div>
    <script src="./popup.js"></script>
  </body>
</html>

當你打開瀏覽chrome://extensions/然後添加插件04-demo

在打開一個測試頁面

我通過插件中的popup.jscontent.js通信,就可以修改我當前頁面上的元素了

另外推薦一個chrome插件官方的例子 chrome-extensions-samples[4],看完一些例子多插件喲更深刻的認識,在下一節裏,我會利用chrome內置緩存能力做一些與我們實際業務相關的例子。

總結

參考資料

[1]chrome: https://developer.chrome.com/docs/extensions/mv3/

[2]manifest: https://developer.chrome.com/docs/extensions/mv3/manifest/

[3]matches: https://developer.chrome.com/docs/extensions/mv3/content_scripts/#programmatic

[4]chrome-extensions-samples: https://github.com/GoogleChrome/chrome-extensions-samples

[5]code example: https://github.com/maicFir/lessonNote/tree/master/chrome-plugin/04-demo

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/32YMmbfjAxl2JWcqDXfx0A