想用Electron做个小工具?这个或许是终极版
故事背景
之前在网上有看到很多小伙伴基于 electron
实现了非常多好用的桌面端工具,比如图床管理工具 PicGo,就专门做图床工具。也有一些其他的类似的小工具,比如 saladict-desktop 专门做沙拉翻译查词的桌面端应用,colorpicker 专做桌面端取色工具...
我们也参考了这些小工具的设计理念,尝试在公司内部做一款桌面端工具,解决网络抓包、代理、图床、性能测评等常见场景的使用问题。最后在推广的时候,遇到了一个比较严重的问题,就是很多小工具对特定用户来说并不需要。比如测试只需要使用网络抓包、代理的功能,其他功能并不关心。此时就需要设计一款桌面端应用,类似于 App Store
那样,用到什么下载安装什么即可。这就需要实现桌面端应用的插件化。
于是乎,我们看到了 uTools 是支持插件化的桌面端应用,但是前提是我们的插件必须发布到 uTools
插件市场,才能实现多端同步下载的功能,但是公司内部的工具库有些涉及到安全信息又无法发布到 uTools
插件中,所以我们特别渴望有一款类似于 uTools
的内部工具箱。
为了进一步提高开发工作效率,最近我们基于 electron 开发了一款媲美 uTools 的开源工具箱 rubick。该工具箱不仅仅开源,最重要的是可以使用 uTools 生态内所有开源插件!这将是巨大的能力,意味着 uTools 生态内所有插件可以无差异化使用到 rubick 中。
代码仓库:https://github.com/clouDr-f2e/rubick
插件化之旅
一开始想到做插件化,无非就是使用 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
目前支持能力
加载utools生态插件
拿 github
上开源的 斗图 插件举例,要加载斗图插件,只需要将代码 clone下来后,复制其 plugin.json
进入搜索框即可使用
斗图:https://github.com/vst93/doutu-uToolsPlugin
超级面板
长按鼠标右键,即可呼起超级面板,可以根据当前鼠标选择内容,匹配对应插件能力。比如当前选择图片后长按右击,则会呼起上传图床插件:
模板
为了更贴合 uTools
的插件能力,需要实现模板功能,模板即是一个内置 UI 样式的功能插件。
utools 自带的系统命令
取色
截屏
全局快捷键
最后
目前 rubick
已经实现 utools
大多数核心能力,最重要的是可以使用 utools 所有生态 ! 更多能力可以前往 github 体验。如果感觉有用,可以帮忙反手一个 star
想用Electron做个小工具?这个或许是终极版的更多相关文章
- 基于python2.7 Tkinter 做一个小工具
1.源码:先写一个界面出来,放需要放入的点击事件的函数 # -*- coding:utf-8 -*- import Tkinter from Tkinter import * import Excle ...
- WPF根据Oracle数据库的表,生成CS文件小工具
开发小工具的原因: 1.我们公司的开发是客户端用C#,服务端用Java,前后台在通讯交互的时候,会用到Oracle数据库的字段,因为服务器端有公司总经理开发的一个根据Oracle数据库的表生成的cla ...
- 18种CSS3loading效果完整版,兼容各大主流浏览器,提供在线小工具使用
今天把之前分享的两篇博客<CSS3实现10种Loading效果>和 <CSS3实现8种Loading效果[二]>整理了一下.因为之前所分享的各种loading效果都只是做了we ...
- 小工具:天气查询 Vs自定义设置 DevGridControl中GridView排序问题 小工具:火车票查询 小工具:邮件发送 小工具:截图&简单图像处理
小工具:天气查询 开发一个天气查询的工具主要由两步构成,一是数据的获取,二是数据的展示. 一.数据获取 数据获取又可以分为使用其它公司提供的API和手动抓取其它网站数据. 1. 某公司提供的AP ...
- 使用abp框架与vue一步一步写我是月老的小工具(1)
一.前言 因为工作的原因,我真正写代码的时间很少,技术面广但深度一直不够,兴趣广泛但缺乏专业精神.以前一直想用asp.net写一款框架,用来在企业开发过程中做一些基础工作,不过后来我找到abp这个框架 ...
- 懒人小工具:T4自动生成Model,Insert,Select,Delete以及导出Excel的方法
之前写了篇文章,懒人小工具:[自动生成Model,Insert,Select,Delete以及导出Excel的方法](http://www.jianshu.com/p/d5b11589174a),但是 ...
- python 3.6 MJ小工具
2017.07.14 update 做了个界面,不需要使用cmd命令行+文件路径的方式来使用了: 链接如下: http://www.cnblogs.com/chenyuebai/p/7150382.h ...
- 懒人小工具:T4生成实体类Model,Insert,Select,Delete以及导出Excel的方法
由于最近公司在用webform开发ERP,用到大量重复机械的代码,之前写了篇文章,懒人小工具:自动生成Model,Insert,Select,Delete以及导出Excel的方法,但是有人觉得这种方法 ...
- QML-AES加解密小工具
Intro 为了解码网课视频做的小工具,QML初学者可以参考一下. 项目地址 Todo 在插入新条目时,ListView不会自动根据section进行重排,因此出现同一个文件夹重复多次的现象.目测强行 ...
随机推荐
- 搭建 Linux 集群环境
什么是集群 集群是一组通过网络互联的计算机,集群里的每一台计算机称作一个节点. 搭建集群环境规划 集群主机节点数:4 台安装 CentOS7 的虚拟机 主机名(Hostname) IP 地址 node ...
- 串口配合DMA接收不定长数据(空闲中断+DMA接收)-(转载)
1.空闲中断和别的接收完成(一个字节)中断,发送完成(发送寄存器控)中断的一样是串口中断: 2.空闲中断是接收到一个数据以后,接收停顿超过一字节时间 认为桢收完,总线空闲中断是在检测到在接收数据后, ...
- Centos7 LVM管理的逻辑卷根目录扩容和/var目录扩容
Centos7 LVM管理的逻辑卷根目录扩容 fdisk /dev/sdb #对新加磁盘进行分区操作pvcreate /dev/sdb1 #创建一个物理卷vgs #查看现有的卷组vgextend ce ...
- 微信小程序在ios系统不兼容new Date('yyyy-mm-dd')
微信小程序中使用new Date('2021-04-01 10:11:20')来转换时间在苹果手机不生效 兼容写法为new Date('2021/04/01 10:11:20')
- synchronized 的超多干货!
前言 synchronized 这个关键字的重要性不言而喻,几乎可以说是并发.多线程必须会问到的关键字了.synchronized 会涉及到锁.升级降级操作.锁的撤销.对象头等.所以理解 synchr ...
- 在js中将map对象转换成json 和 js对cookie的操作
在js中将map对象转换成json //msp转objectlet obj= Object.create(null); for (let[k,v] of map) { obj[k] = v; }//o ...
- MindSpore后端运行类
MindSpore后端运行类 Q:如何在训练过程中监控loss在最低的时候并保存训练参数? A:可以自定义一个Callback.参考ModelCheckpoint的写法,此外再增加判断loss的逻辑: ...
- onnx算子大全
本文通过此脚本从def文件自动生成.不要直接修改,而是编辑算子定义. 对于算子输入/输出的可辩别的,它可以是可辩别的.不可辩别的或未定义的.如果未指定变量的可辩别的,则该变量具有未定义的可辩别的. a ...
- 第五周 Spring框架
一.Spring框架设计 Spring framework 6大模块 1.1 Spring AOP AOP: 面向切面编程 Spring 早期版本的核心功能,管理对象声明周期和对象装配 为了实现管理和 ...
- .NET平台系列22:.NET Core/.NET5/.NET6 对比 .NET Framework
系列目录 [已更新最新开发文章,点击查看详细] 在我的博客<.NET平台系列2 .NET Framework 框架详解>与 <.NET平台系列7 .NET Core 体系结构 ...