開源版本的 uTools。可支援 uTools 所有插件生態
- 2021 年 6 月 29 日
- 筆記
話不多說,先放上截圖和倉庫地址:
故事背景
網路抓包
之前公司內部因為開發需要,需要和後端進行介面聯調,測試環境的時候,經常會涉及到一些狀態改變要看交互樣式的問題。比如測試需要測商品的待支付、支付中、支付完成等各種節點的交互樣式是否符合預期,這種情況測試一般會去造數據或者讓後端改資料庫介面。 有的小夥伴可能會用 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="//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: //github.com/clouDr-f2e/rubick-plugin-demo
Far from enough 這只是開始
載入 utools 生態插件
斗圖: //github.com/vst93/doutu-uToolsPlugin
窗口分離
utools doc 模板
uTools 的插件開發給予了開發者最大的自由度,你可以隨心所欲的設計頁面結構、樣式、交互,對於特別擅長前端開發的同學,這沒有什麼問題,但對於非前端開發者,要做出漂亮的、高品質的前端 UI 是一件困難的事情。
所以 Rubick 也實現了模板能力:
utools 自帶的系統命令
取色
截屏
最後
目前 rubick 已經實現 utools 大多數核心能力,最重要的是可以使用 utools 所有生態 ! 更多能力可以前往 github 體驗。如果感覺有用,可以幫忙反手一個 star ✨