用Chrome外掛改進開發體驗

大桔子發表於2021-11-28

用Chrome外掛改進開發體驗

事件背景

  • 由於公司的部分老專案(數量還挺多)前端是用hybird方式和app混合開發,前端的登入態是靠app開啟時在url拼接一個token,開發環境除錯時候用charles抓包,將頁面url取出來(url裡面帶有token),這樣就能開發時在本地模擬使用者登入狀態
  • 問題:由於開發環境賬號服務不是很穩定,並且經常用的一些測試賬號又有好多人在用,這樣就導致一個問題:token總是頻繁失效
  • 以前token失效時,就再用app重新登入或換賬號登入,然後繼續用charles抓出新的token,這個過程不僅浪費時間而且還挺煩人

解決方法

  • 想到開發一個Chrome外掛,在外掛裡輸入手機號和密碼然後自動將獲取到的token拼進開發環境訪問的url裡
  • 效果如下:點開Chrome外掛,輸入手機號、密碼,點選確定會將獲得的token拼進當前頁面url裡,如果當前url裡已存在token(即過期token)則將其替換掉
    chrome-2.png

如何開發一個Chrome外掛

  • 主要通過這篇文章學習的【乾貨】Chrome外掛(擴充套件)開發全攻略官網
  • Chrome外掛可以實現非常強大的功能如我們常用的 redux-devtoolvue-devtool掘金外掛
  • 基礎概念在這裡就不贅述了,上面的那篇教程應該能解決大多數問題,如果解決不了那就看官方文件

我的Chrome外掛mock_token的實現

  • 我這裡主要用到了browserAction的展現形式即上圖所示
  • 開發步驟:
  • 必備一個 manifest.json 檔案 重點兩個配置:content_script/browser_action

        "name": "Mock_Token",
        "version": "2.1",
        "description": "一個獲取使用者token的外掛",
        "manifest_version": 2, // 此處必須是2
        // 直接注入當前頁面的js
        "content_scripts": [
            {
                "matches": ["http://localhost/*"],
                // 直接注入頁面
                "js": ["content.js"],
                "run_at": "document_start"
            }
        ],
        // 瀏覽器狀態列的展示
        "browser_action": {
            // 外掛圖示
            "default_icon": "32.png",
            // 外掛標題
            "default_title": "獲取token-Chrome外掛",
            // 外掛的展現頁面即一個HTML檔案
            "default_popup": "./popup.html"
        },
        // 外掛所需要的許可權
        "permissions": ["storage", "webRequest", "tabs", "http://*/*", "https://*/*"],
        // csp安全策略設定,否則在HTML外鏈引入jQuery的時候會報csp安全錯誤
        "content_security_policy": "script-src 'self' https://cdn.bootcdn.net; object-src 'self'"
  • popup.html即點選瀏覽器狀態列彈出的模態框

    <!DOCTYPE html>
    <html lang="en">
    <!-- head省略 -->
    <head></head>
    <!-- 樣式省略 -->
    <style></style>
    <body>
        <input id="phone" type="text" placeholder="請輸入手機號" maxlength="11">
        <input id="pwd" type="text" placeholder="請輸入密碼" maxlength="6">
        <button id="btn">確定</button>
    </body>
    <!-- 引入外鏈js庫必須要在manifest.json裡面配置CSP安全策略 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <!-- 此檔案不可寫內聯script標籤,必須用引入方式 -->
    <script src="./popup.js"></script>
    </html>
  • popup.js 即模態框內容的互動邏輯

     const phone = document.querySelector("#phone");
     const pwd = document.querySelector("#pwd");
     const btn = document.querySelector("#btn");
    
     // 頁面初始化的先從Chrome的storage裡面讀取上次填寫的手機號密碼
     chrome.storage.sync.get({ phone: "", pwd: "" }, function (items) {
         phone.value = items.phone;
         pwd.value = items.pwd;
     });
    
     btn.addEventListener("click", () => {
         getToken(phone.value, pwd.value);
         // 每次點選確定的時候將手機號密碼寫入儲存
         chrome.storage.sync.set({ phone: phone.value, pwd: pwd.value }, function () {
             console.log("儲存成功!");
         });
     });
    
     function getToken(phone_no, password) {
         let params = {
             phone_no: phone_no || "10012345632",
             password: password || "123456",
         };
         const url = "https://xxx.com/login?args=" + JSON.stringify(params);
    
         fetch(url).then((res) => res.json())
             .then((res) => {
                 sendMsg(res.token)
             });
     }
    
     // 通過postmessage的形式將資訊傳給content-script
     // 因為popup.html 不能操作當前宿主頁面而content-script要將資訊傳遞出去
     // 另外一點值得提的是當前檔案可以無視跨域直接調介面而content-script受跨域限制
     function sendMsg(token) {
         chrome.tabs.query({ active: true, currentWindow: true}, 
         (tabs) => {
                 const message = { token };
                 chrome.tabs.sendMessage(tabs[0].id, message);
             }
         );
     }
  • content.js 即由content-script直接注入到宿主頁面內

    // onMessage 監聽 popup.js傳遞過來的資訊
    chrome.runtime.onMessage.addListener((req, sender, sendResponse) => {
        console.log("接收了來自 popup.js的訊息", req.token);
        replaceToken(req.token);
    });
    
    // 直接替換當前url中的token
    function replaceToken(token) {
        const url = window.location.href;
        if (!url.includes("token")) {
            window.location.href += url.includes("?")
            ? `&token=${res.token}`
            : `?token=${res.token}`;
        } else {
            window.location.href = url.replace(/(token=)[^&]+/, "$1" + res.token);
        }
        // 單頁面應用由於直接改變token頁面不會重新整理,所以需要手動reload一下
        setTimeout(() => window.location.reload();, 500);
    }

    關於除錯

  • content.js裡面的內容可以直接在當前頁面的控制檯進行除錯
  • popup.js裡面的內容要單獨開啟一個控制檯,操作如下圖所示
  • chrome-3.png

    總結

  • 以上就是該外掛開發的全部內容-非常簡單??[旺柴]
  • 當然Chrome外掛本身還是可以開發很多好玩有用的東西,比如如果要實現的功能非常複雜完全可以引入像React/Vue等現代的前端開發框架

相關文章