話不多說,先放上截圖和倉庫地址:
故事背景
網路抓包
之前公司內部因為開發需要,需要和後端進行介面聯調,測試環境的時候,經常會涉及到一些狀態改變要看互動樣式的問題。比如測試需要測商品的待支付、支付中、支付完成等各種節點的互動樣式是否符合預期,這種情況測試一般會去造資料或者讓後端改資料庫介面。 有的小夥伴可能會用 Charles
修改返回資料進行測試。但是 Charles
的抓包體驗和配置體驗感覺有點麻煩,不是很友好,所以我們自己做了個抓包&mock工具:
傻瓜式互動一次性解決:抓包、代理、請求轉發、介面資料篡改 mock 、跨域訪問 等能力,並得到了廣泛使用和好評。
檔案上傳
隨著專案開發的繼續,有些使用者給我們反饋頁面載入圖片資源比較慢,我們看了一下很多圖片資源都沒有經過壓縮處理,這個時候我們可以通過 webpack 寫了一些 loader 來對圖片資源進行壓縮處理。這個時候我們的圖片資源大部分是存放在專案目錄下。而有的時候,我們是需要將圖片存放於 cdn 上的,此時我們又需要一個圖床工具,可以線上儲存圖片資源。於是乎,我們又整合了圖片壓縮和上傳的功能,做了個圖床工具:
效能測評
開發者開發頁面的時候,需要對頁面的效能進行評估,另一方面也可以把評估報告通知給測試同學,對其進行效能測試。之前大多采用的是 chrome 外掛 lighthouse 來做。但是這個東西對未登入使用者無法做到效能評估,因為使用者未登入直接測評了登入頁面,顯然不符合預期,其次,每個電腦上都得安裝外掛,受限於裝置的不同,可能會導致效能沒有同一的變數(網路、網速、解析度、CUP 等)。所以我們基於 pupeeteer-core
以及electron 做了一個免登的測評工具:
但是這些還遠遠不夠,我們隨著業務的增加,功能愈發的多了起來:我們的埋點檢測工具、需求管理工具、前端多環境切換工具 等等等....一方面導致 electron 體積變得臃腫起來,另一方面隨著釋出頻率增加,安裝下載的成本也越來越大,很多使用者就不願意再接著安裝,因為確實很麻煩。所以我們需要改變,讓功能不依賴與容器。這就需要把我們的功能全部獨立出去,做成外掛化。所以我注意到了 utools
外掛化之旅
一開始想到做外掛化,無非就是使用 electron 的 webview 能力,實現類似於原生內嵌h5那樣的方式,h5 頁面可以做獨立釋出,原生提供 nativaAPI 之間通過 jsBridge 來橋接呼叫原生的方法。這樣實現並無問題,我們也嘗試了做了一次。最終思路大概是:
electron webview 方式
1. electron 中使用 webview
<webview src="https://xxx.xx.com/index.html" preload="preload.js" />
2. 實現 bridge
// preload.js
window.rubickBridge = {
sayHello() {
console.log('hello world')
}
}
3. 外掛藉助 bridge 呼叫 electron 的能力
<html>
<body>
<div>這是一個外掛<div>
</body>
<script>
window.rubickBridge.sayHello()
</script>
</html>
4. 通訊
因為 proload.js 是 electron 的 renderer 程式的,所以如果需要使用部分 main 程式的能力,則需要使用通訊機制:
// main process
ipcMain.on('msg-trigger', async (event, arg) => {
const window = arg.winId ? BrowserWindow.fromId(arg.winId) : mainWindow
const operators = arg.type.split('.');
let fn = Api;
operators.forEach((op) => {
fn = fn[op];
});
const data = await fn(arg, window);
event.sender.send(`msg-back-${arg.type}`, data);
});
// renderer process
ipcRenderer.send('msg-trigger', {
type: 'getPath',
name,
});
ipcRenderer.on(`msg-back-getPath`, (e, result) => {
console.log(result)
});
為什麼後來我們又放棄了這條路? ?
其實上面的思路大致是沒啥問題的,我們也基於上面的思路成功把功能抽成了外掛,按照外掛的方式進行安裝載入。直到我們注意到 utools 的強大,感覺 utools 的生態非常豐富,我們要是能整合 utools 的生成那該多好呀!所以我們秉持著幹不過他就成為他的原則,我們嘗試著成為他。但是 utools 本身並沒有開源,所以沒有辦法去吸取一些優秀的程式碼實現,但是我們可以看他的官方文件。
我們發現其實 utools 大多數外掛都是和 container 層分離的,也就是說 utools 只是一個外掛的容器,為外掛提供了一些 api 能力和方法。所以一旦我們實現了utools載入外掛的能力,實現 utools 的所有 API 函式,是不是就約等於實現了 utools ! 我們就可以使用 utools 的外掛?
utools 方式
按照 utools 的 文件,首先我們需要實現一個外掛,必須要有個 plugin.json,這玩意就是用來告訴 utools 外掛的資訊。我們也按照文件來寫:
{
"pluginName": "helloWorld",
"description": "我的第一個 uTools 外掛",
"main": "index.html",
"version": "0.0.1",
"logo": "logo.png",
"features": [
{
"code": "hello",
"explain": "hello world",
"cmds":["hello", "你好"]
}
]
}
接下來是將寫好的外掛用 utools 跑起來,按照 utools的互動是複製 plugin.json 到utools搜尋框即可,我們也可以實現:
// 監聽 input change
// 讀取剪下板內容
const fileUrl = clipboard.read('public.file-url').replace('file://', '');
// 複製檔案
if (fileUrl && value === 'plugin.json') {
// 讀取 plugin.json 配置
const config = JSON.parse(fs.readFileSync(fileUrl, 'utf-8'));
const pluginConfig = {
...config,
// index.html 檔案位置,用於 webview 載入
sourceFile: path.join(fileUrl, `../${config.main || 'index.html'}`),
id: uuidv4(),
type: 'dev',
icon: 'image://' + path.join(fileUrl, `../${config.logo}`),
subType: (() => {
if (config.main) {
return ''
}
return 'template';
})()
};
}
實現效果如下:
接下來就是進行命令搜尋外掛:
實現這個功能其實也就是對之前儲存的pluginConfig的裡面的 features 進行遍歷,找到相應的 cmd 後進行下拉框展示即可。
然後我們要去實現選擇功能,用 webview 載入頁面的能力:
<template>
<div>
<webview id="webview" :src="path" :preload="preload"/>
</div>
</template>
<script>
export default {
data() {
return {
path: `File://${this.$route.query.sourceFile}`,
preload: `File://${path.join(__static, './preload.js')}`,
webview: null,
query: this.$route.query,
config: {}
}
}
}
</script>
到此結束了?並沒有!!!由於篇幅的原因,我們後續再說。本出寫的外掛 demo 已上傳 github: https://github.com/clouDr-f2e/rubick-plugin-demo
Far from enough 這只是開始
載入 utools 生態外掛
鬥圖: https://github.com/vst93/doutu-uToolsPlugin
視窗分離
utools doc 模板
uTools 的外掛開發給予了開發者最大的自由度,你可以隨心所欲的設計頁面結構、樣式、互動,對於特別擅長前端開發的同學,這沒有什麼問題,但對於非前端開發者,要做出漂亮的、高質量的前端 UI 是一件困難的事情。
所以 Rubick 也實現了模板能力:
utools 自帶的系統命令
取色
截圖
最後
目前 rubick 已經實現 utools 大多數核心能力,最重要的是可以使用 utools 所有生態 ! 更多能力可以前往 github 體驗。如果感覺有用,可以幫忙反手一個 star ✨