iT邦幫忙

2022 iThome 鐵人賽

DAY 20
0
Modern Web

你知道這是什麼嗎? Chrome Extension MV3 With Vite系列 第 20

你知道這是什麼嗎? Chrome extension MV3 With Vite - Day 20 用 Vite 實現 套件自動更新

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20220920/20139636T5ZGQzumWX.jpg
Hi Dai Gei Ho~ 我是Winnie ~

在昨天文章中我們簡單介紹 Vite 基本內容與設定後,在此篇文章中我們要來說說如何透過Vite實現開發熱更新。

為什麼要熱更新?

事情是這樣的,由於 Extension 不像開發網站一樣有開發的運行環境可以測試使用,只能透過 開發人員模式上傳 測試的套件包 來運行,所以每當程式碼修改時,也就只能手動重整來更新測試套件是否正常,如果還使用 Vite 或其他打包工具來開發時,就會多出來一個動作,要額外再編譯程式碼。

咦,那什麼是熱更新 ?

HMR 熱更新

熱更新 英文全名為 Hot Module Replacement,簡稱HMR,也就是說在開發時當程式碼修改時,能透過不刷新網頁的情況下,將修改的模組(Module)更新成新的內容,同時不會影響其他模組(Module)的運作。

但這邊要解釋下,雖然Vite也有自帶HMR,但因為在開發模式啟動的 devServer,在 Extension 開發中無法使用,所以在此篇文章所說的 熱更新 是我們要基於 Vite 的現有的設定功能 來自己簡單做一個 HMR。

而在這邊主要解決兩個問題:

  1. 當程式碼修改,專案會自動編譯
  2. 當打包完成,重整套件包內容 或者 網站頁面

自動重新編譯

我們先來看看第一個問題:

關於自動編譯的功能,在 Vite 有提供一個 vite build --watch 可以使用,只要在package.json"scripts"腳本中新增即可

注意: 這邊的 "build-watch" 可以自己定義名稱


{
  "scripts": {
    "dev": "vite", //dev模式
    "build": "vite build", // 打包模式
    "build-watch": "vite build--watch", // watch 打包模式 
    "preview": "vite preview" //預覽模式
  }
}

當新增 build-watch 指令後, 我們可以透過 vite build-watch
來打包專案,此時就會進入watch模式中,當需要編譯的檔案有修改時,就會即時編譯。

處理自動編譯的問題之後,接著我們來看看第二個問題

自動重整 Extension

在 自動重整 更新Extension 前,首先我們要知道 Vite 何時打包完成,且通知當前套件自動重整。

整個流程大概切分三個步驟:

打包完成dev server 通知 Extension 與 Browser 執行重整更新

1. 監聽 打包完成

由於在 Vite 文件中 尚無提供關於 如何監聽編譯完成 的方法,所以在這邊我們只好透過 Rollup 提供的 Output Generation Hooks 來自定義 Vite Plugin , 實現 監聽編譯完成的事件。

Rollup 為 Vite 主要打包工具,是基於ES2015的JavaScript編譯工具,同時相較於其他打包工具,其能讓編譯過後的檔案容量更小、速度更快。

// build_watch.js

export default () => {
  return {
    name: "build_watch"
    closeBundle() {
      // 編譯結束時...
    },
    watchChange() {
     //程式碼修改時...
    },
    closeWatcher() {
     //關閉watch時...
    }
  }
}

2. 通知 Extension 與 Browser

接著要通知 Extension 與 Browser 重整,我們可以透過創建一個WebSocket與頁面連接。

先安裝 WebSocket:

pnpm add -D ws

接著 透過 config 來判斷目前的指令是否為build-watch模式,如果是創建一個 WebSocket server 同時監聽連接事件。

    // build_watch.js
    ...略
    name: "build_watch",
    config: (config, {
      command
    }) => {
      //在 build 且 watch 下使用
      const canUse = command === 'build' && Boolean(config.build.watch)

      if (canUse) {
        // 創建 WebSocket
        wss = new WebSocketServer({ port: 2333 })
        wss.on('connection', (client) => {
            console.log('client:',client)
            ws = client
        })
      }
    }
    ...略

接著 使用 rollup 中 Output Generation Hooks 的 closeBundle() 寄送訊息通知頁面

import {
  WebSocketServer,
  WebSocket
} from 'ws'

let ws = WebSocket;
let wss = WebSocketServer;
let timer;

const send = (msg) => {
  // 如果當前沒有 sw  就取消通知;
  if (!ws) return
  msg = JSON.stringify(msg)
  
  //通知頁面
  ws.send(msg)
}

export default () => {
    return {
            ...略
        closeBundle() {
              timer = setTimeout(() => send('watch-build-ok'), 500)
            },
        watchChange() {
          clearTimeout(timer);
        },
        closeWatcher() {
          // 如果 ws & wss 就執行 .close()
          ws && ws.close()
          wss && wss.close()
          clearTimeout(timer)

          //清空  ws
          ws = null;
          wss = null;
          timer = null;
        }
    }
}
    

這邊加入timer延遲的原因為 當程式碼多次修改時,第一次編譯完成會觸發 closeBundle ,馬上又會進行重新編譯,此時如果立刻通知其頁面更新,因為第二次編譯還沒完成,當編譯完成時就無法通知到對應的頁面 造成重新整理失敗。

所以需透過 closeBundle hook 加入timer來延遲,同時在watchChangehook來 重新計算時間。

3. 在 vite config 引入 自訂義 plugin

import buildWatcher from './.vite/plugin/build_watch';

export default defineConfig({
    plugins: [
         buildWatcher()
    ]
})

4. 重新整理

判斷透過 環境變數 判斷當前是否為開發模式,如果是連接 WebSocket,且監聽 onmessage 事件,如果為此訊息透過chrome.runtime.reload()來重整套件。

//popup.js

if (import.meta.env.DEV) {
  const ws = new WebSocket('ws://localhost:2333')
  ws.onmessage = (event) => {
    let msg = JSON.parse(event.data)
    if (msg === 'watch-build-ok') {
      chrome.runtime.reload()
    }
  }  
}

這段程式碼最終在 vite build 模式下,會透過tree shaking 移除

以上就是關於 用Vite實現Extension開發熱更新的介紹,那今天文章先到這邊了,謝謝願意花時間看此篇文章的你,如果文章有錯誤的地方,再麻煩不吝嗇的給予指教,感謝!!

今日想推薦 -> 當我們一起走過


上一篇
你知道這是什麼嗎? Chrome extension MV3 With Vite - Day 19 用 Vite 創建一個 Extension 吧
下一篇
你知道這是什麼嗎? Chrome extension MV3 With Vite - Day 21 Extension 中的 ES6 Module
系列文
你知道這是什麼嗎? Chrome Extension MV3 With Vite30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言