共计 6196 个字符,预计需要花费 16 分钟才能阅读完成。
说到前端写 Windows
应用程序,首先想到的肯定是 Electron
,这次咱们换一个小众点的工具aardio
。aardio
是一个很轻量的工具,有着本人的语法,只
面向 windows
利用开发,刚好其中也有反对前端利用打包性能。
选型
aardio
中波及到 HTML
+CSS
+JS
的性能。有 Chrome App
、Electron
,同时还有Sciter.js
、HTMLayout
两个 UI 引擎。
一下子就有四种选项,这里按本人摸索的简略总结一下,可能会不太精确:
Chrome App
默认打包进去的应用程序不携带浏览器,程序会启动调用本地的浏览器渲染 (不限于官网的Chrome
,Edge
以及国产支流 Chromium
内核的浏览器都行),如果都没有会主动装置微软的 Edge(Chromium 版)
浏览器。
劣势是生成体积比拟小(但外部环境不稳固,产生的显示 Bug 可能性也更多),根底大小预计在 800KB
左右(经 UPX 压缩过),前端我的项目迁徙起来不必过多批改就能跑起来。如果要指定环境,也能够在启动代码内指定浏览器门路。
Electron
能够构建 Electron
的利用,Electron
自身就是做桌面程序的为什么还须要应用 aardio
?
看了一下,除了能够利用 aardio
的一些内置的不便性能函数,同时生成的利用体积也是差别很大,软件自带的示例 Electron
我的项目生成文件大略在 800KB
左右(经 UPX 压缩过),作者可能应用了精简版的内核替换了本来的程序。如果只做 Windows 平台利用,这样的打包体积还是很吸引人的。
Sciter.js
这次要是面向桌面开发的一个 UI 渲染引擎,能够利用 HTML
+CSS
写界面,将浏览器许多无用性能剔除,只留下 UI 引擎罕用的性能,使得体积尽量玲珑。
本来认为能将整个前端我的项目打包进去,但尝试了一下,如同不行。HTML
与 CSS
是独自传入的,没方法像是前端那么自在的援用。应用逻辑更像是一个 html
界面就配置一个 Sciter.js
对象,而不是将 html
程序的所有逻辑放到外面去执行。
生成的利用体积也是比拟小的,大略在 2.8MB
左右(经 UPX 压缩过)。看介绍,大部分罕用的 CSS
反对,同时也有一些非凡的语法不便解决界面。
HTMLayout
HTMLayout
是 Sciter.js
的前身,程序体积更小,但反对的 CSS
性能也更加无限。同样也不太实用前端我的项目的打包。
比照了一下 HTMLayout
和Sciter.js
生成利用的体积,利用大略在 1.5MB
左右(经 UPX 压缩过),两者只差了 1.3MB
左右,但放弃的新语法可能要很多,所以这个大部分场景能够不用思考了。
尝试一下
官网有推过一个修改版的 hostsSwitchHelper
,应用的就是Chrome App
模式,既然是尝试,那就先选这个模式来试试。
Chrome App
模式其实很小白,如果没有与零碎交互的性能,那么简直就是间接将前端我的项目编译,而后导入到开发工具中就能生成一个利用。
先来看看界面:
比拟传统的 IDE 界面,左上角的 Logo
点开,而后点击 新建工程
,能看到新建窗口。
抉择 Web 界面
栏目,而后抉择第一项 Chrome App
,设置好目录就能创立出一个Chrome App
例子了,其中自带曾经能跑起来的代码。
代码量很少,不相熟的能够间接在这个我的项目上做简略批改,就是一个本人的我的项目了。
做一个本人的程序
这是已实现的界面:
前端局部
先从相熟的开始吧,把前端局部先实现。
因为程序不大,于是不应用 Vue
或者 React
了,找了个原生丑陋的 UI 框架LuLu UI
,配合TypeScript
,打包工具也不要太重的WebPack
,咱们选用更加轻量的parcel
。
其实一开始是间接用 LuLu UI
+ 原生 JS,简略的写几个页面,起初对界面细节一直调整(这块重复批改花了不少工夫),以及操作逻辑的优化,总体逻辑绝对简单了起来,于是引入了打包工具,将CSS
换成了 LESS
,JavaScript
换成了TypeScript
,并且分出了目录构造进去。
打包其实只须要编译实现的前端文件,所以前端工程能够随便放在哪儿都行,最初只须要把编译出的文件放到 aardio
设置的目录下就能够了。
至于前端就很一般,常见的建设我的项目,补充款式与逻辑,加上 parcel
自身也很轻量易用,太细节的就不多说了,挑一些次要的说。
敞开翻译提醒
如果不设置,网页默认是英文,关上后 Chrome
会弹出翻译提醒,这个性能对于本地应用程序无意义。设置的话就是标注网页语言为中文,或是简略粗犷在 head
标签里加上这句,禁止应用翻译性能。
<meta name="google" content="notranslate" />
屏蔽影响应用的快捷键
网页的 F12
、Ctrl+Shift+i
、Ctrl+u
等,万一触碰到会影响应用程序体验,用 JS 代码将这些快捷键禁用。
因为 KeyboardEvent.keyCode
曾经被废除了,这里间接应用 KeyboardEvent.key
判断
window.onkeydown = window.onkeyup = window.onkeypress = function (event: KeyboardEvent) {
// 禁止 ctrl+u
if (event.ctrlKey && event.key.toLowerCase() == 'u') return false;
// 禁止 ctrl+s
if (event.ctrlKey && event.key.toLowerCase() == 's') return false;
// 禁止 ctrl+shift+i
if (event.ctrlKey && event.shiftKey && event.key.toLowerCase() == 'i') return false;
// 禁止 F5
if (event.key == 'F5') return false;
// 禁止 F12
if (event.key == 'F12') return false;
};
屏蔽右键
右键的菜单也有无关动货色,影响应用体验,重点还很难看。如果没有右键性能能够间接屏蔽,这里为了不便加上了右键性能,所以重画了右键菜单键,替换了原生的右键。
window.oncontextmenu = function (event: MouseEvent) {event.preventDefault();
show(event); // 外面包含关上本人的菜单层
return false;
};
document.addEventListener('click', close); // 敞开右键菜单 close 函数里就是将相应的层暗藏
show
的逻辑很简略,获取以后鼠标地位,而后判断窗口是否会溢出,做相应的高度批改,最初将指定的菜单层显示。
/**
* 显示右键菜单
* @param {MouseEvent} event
*/
function show(event: MouseEvent) {if (!isNavItem(event)) return;
// 获取以后鼠标地位
let mouseX = event.clientX;
let mouseY = event.clientY;
// 判断边界值,避免菜单栏溢出可视窗口
const winHeight = document.documentElement.clientHeight ?? document.body.clientHeight;
// BUS.contextMenu 是存储的前端菜单 DOM
if (mouseY > winHeight - BUS.contextMenu.offsetHeight) mouseY = winHeight - BUS.contextMenu.offsetHeight - 10;
else mouseY = mouseY;
BUS.contextMenu.style.left = `${mouseX}px`;
BUS.contextMenu.style.top = `${mouseY}px`;
}
这里减少了一些细节判断,像是编辑器区域不弹出右键,在标签项右键与导航空白区右键显示不同菜单。
调试模式
因为禁用掉开发者工具在调试的时候很麻烦,通过正文代码屏蔽又容易遗记,parcel
打包工具同样提供了环境变量。
process.env.NODE_ENV === 'production'
网页元素重渲染
因为没有应用古代框架,这部分起始逻辑很重。像是鼠标右键不同中央显示不同菜单的性能实现起来就会很麻烦,要不然代码就很冗余。于是引入了玲珑快捷的前端模板引擎art-template
,一部分操作交给引擎判断,通过增加不同的类名展现不同的状态。
比方鼠标右键点击在标签项上,如果以后的项没有增加 url
参数,则是本地的 Hosts
,渲染时会增加disabled
类名,标识禁用此元素。disabled
类的 CSS
外围是pointer-events: none;
,这样即可让此元素不响应鼠标事件,无需再增加多余的 js 逻辑。
导航栏的以后选中的类名增加、增加新项等操作全副只是在对立的数据中做记录,而后依赖从新渲染一次性替换掉 HTML
,防止了写简单简短的DOM
增删逻辑,也简化了代码耦合。
所以我的项目里独自做了一个数据管理的模块。从本来的简略 nav
渲染单文件逻辑开始,到起初因为 UI 逻辑越做越粗疏,这个里也从单文件变成了多文件,尽量把内部操作与纯数据操作隔离。
文本编辑器
如果应用 textarea
标签能够实现多行文本,但没方法提供正文文字的辨别显示,也没方法提供行号、快捷键、搜寻等扩大性能,所以咱们须要一个文本编辑器。
通过筛选比拟常见的代码编辑器有 CodeMirror
、aceEditor
、monacoEditor
(VS Code
的前身),三者中 CodeMirror
体积最小,咱们须要的性能也不要太多,于是就选这个了。
应用办法网上很多,源码中正文也很分明,应用形式就不多提了。
语法色彩
因为咱们的 Hosts
理论只须要给 #
号上色,编辑器有相似的语法,但也会将多余的关键字和构造显示出色彩,这时候咱们能够本人批改一个。
简略的翻阅语法源码能发现在 tokenBase
和return
中的 token
有对很多信息做匹配,将没有的信息删除,缩小判断逻辑,连带的能够删除几个相干函数代码。之后在底部 CodeMirror.defineMIME
中有自定义许多关键字,对咱们也没用,都能够删除。而后记得改一个新名字,这样就实现了一个咱们专门的语法,导入插件中就能应用了。
主题款式咱们也能够自定义,同样是找一份看的不错的款式,而后把 CSS
代码复制过去,其中有许多状态的款式名称,依据相应名称修色彩即可。
这里我开启了高亮选中行,所以在以后行会有一个蓝色底色,因为我在编辑器文本框背景上又加了一个以后项的类型图标,会导致图标被笼罩,这时候只须要将 div.CodeMirror-selected
的色彩调成半透明模式即可,但因为我背景的透明度调的很低(背景透明度是 0.06,而选中的透明度是 0.8),所以不认真看的话实际上还是有点像是被覆盖住。
快捷键
自身是做切换标签才主动保留的逻辑,但如果用户批改了文本内容,误以为是实时保留而间接敞开软件,这样就会导致批改失落。所以须要加上一个以后文本批改过的标识,于是又在右上角加了一个保留按钮(一个不难看,顺便又加上了刷新与更新近程文件按钮)。
有了按钮,天然的会习惯用 Ctrl+s
去保留文件,好在 CodeMirror
是提供了自定义快捷键的。
extraKeys: {'Ctrl-S': eventTextareaSave, // 这里是自定义的保留逻辑}
网络申请及代理
常见的利用场景是从网络上复制他人整顿好的 Hosts
信息,所以为了不便减少了从网络获取 Hosts
性能。但这种个别须要借助代理性能能力获取到,搜寻网上并没见到 js 能间接设置代理的方法。
这时候就应该将前端不易操作的性能放到 aardio
中,通过 inet.http
库能够间接发动网络申请,同时默认也会走零碎代理设置,齐全满足了目前的性能所需。
aardio 局部
到这里就进入了咱们不是相熟的局部了。aardio
语法很像 js,但细节上跟 js 又有差距,所以写起来的时候很容易弄混,要留神一下。
这里说几个看目前代码须要了解的点:import
,是将对应的命名空间导入以后的命名空间,应用的时候能够间接应用。会按 内核库
、 规范库
、 用户库
(应用程序 lib 目录)查问引入。var
,申明变量不肯定都要应用var
关键字,如果没应用是默认挂在以后命名空间下的。如果应用了,则作用域是在以后代码块。同时申明变量也只有 var
关键字,不要棘手把 ES6
的关键字用上了。global
,这是默认的全局空间名字,简写是 ..
在代码中常常看到,比方要操作 io
库,能够写成 ..io
调用。table
,aardio
里 table
是一种类型,相似 js 里的数组和对象,两种类型同时是 table
类型。写法上 key
和value
连贯是用 =
,开端完结是用;
,这个与 js 差别很大,不小心写错会导致报错,复查错觉无时往往容易因为惯性而疏忽。 多返回值
,程序是反对多返回值的,用,
分隔,接管返回也是间接用 ,
分隔写变量即可接管。目录环境
,门路如果是~
结尾的代表 exe
利用程序运行的当前目录,如果是在测试环境,则是 aardio.exe
主程序的目录。
其余不必写大段逻辑的话,根本也能看懂了。
创立 chrome 程序
main.aardio
是程序主入口,在这个文件里写起始逻辑。
import chrome.app; // 导入所需的库
var theApp = chrome.app(); // 创立一个实例
theApp.start(url); // chrome 关上指定的 url
这样就能启动一个 chrome
利用了。
js 与 aardio 交互
theApp.external = {key = function(){// 逻辑};
}
在 external
外面传入相应的逻辑,前端通过 aardio
组件能够实现调用。
引入前端文件
在左侧新建“虚拟目录”,右侧会呈现设置项,“目录门路”批改成咱们前端的门路,“内嵌资源”要选true
,不然无奈生成单文件的应用程序。
最初对着这个虚拟目录单击右键,抉择“同步本地目录”,如果目录内有文件的话会全副显示进去。如果有批改从新生成前端文件的话,也要记得手动同步一次,目录是不会主动刷新的。
编译利用
这样咱们的前端我的项目就能打包成 win 的应用程序了,按 F7
就能一键编译,略微等一儿编译好的利用就生成了,是不是很简略?
Electron 版尝试
在 aardio
中Electron
做了简化,目前的我的项目能够间接复制到 Electron
工程的 渲染过程
中应用,只有启动代码做相应批改即可。但尝试下来,发现 UI 渲染非常卡顿,不晓得是什么起因。目前性能临时够用,这块等之后有空再理解吧。
结尾
总体应用下来,对于相熟前端以及前端工具链的模式,aardio
的界面和文本编辑器很不适应(VS Code
上有人做了一个插件,说是能够间接在 VS Code
编译,配置了仍然报错,而且没有格式化,没有智能提醒,反不如原生 IDE 不便)。
文档也绝对比较简单,须要有肯定的急躁,很多中央须要本人从右侧的范例中查找例子学习,如果没有例子,则要从左下角的规范库里,看源代码和智能提醒理解具体有什么性能和如何编写代码。
我的项目源码
具体细节有趣味的话请查阅源码:HostsSwitch
https://github.com/Lnncoco/ho…