一、为什么要学习Electron,适合什么场景?
1、为什么要学?
-
可以帮你快速构建一个桌面端应用(可用于快速试错)。
-
可以用来造工具。
-
提升技术广度和视野。
Electron是Web的超集,它基于JavaScript环境,能够让前端工程师快速上手,同时会接触到Node.js、客户端知识、甚至更底层的操作系统,能够让前端工程师的想象力从浏览器中释放出来,丰富自己的知识储备,提升技术广度和视野。
2、Electron适合用在什么场景?
-
要快速试错,占领市场时
-
开发工具,效率应用时
- 要同时开发Web版和桌面版时
3、谁在用Electron
- Atom
- slack
- VS Code
- WordPress
二、学习Electron的难点在哪
1、涉及的技术栈比较多
需要了解Electron知识、客户端知识、Node.js,甚至是集成C++或者Rust等第三方库,会涉及到多进程的概念等等
2、大部分公司Electron相关的基础建设比较匮乏
比如在Mac打包的时候,可以依赖iOS持续集成,而在Windows上则不行,类似场景还特别多。
3、如何充分利用好Electron的能力
前端工程师习惯于局限在基于浏览器的能力进行开发的思维中。
三、Electron是什么
1、它是由Github开发的开源框架,现在有OpenJS基金会维护的一个开源项目。
2、它允许开发者使用Web技术构建跨平台桌面应用。
3、Electron = Chromium + Node.js + Native API
其中,
Chromium提供强大的UI能力,让其可以在不考虑兼容性的情况下,利用强大的Web生态来开发界面;
Node.js让Electron有了底层的操作能力,比如文件读写,加解密,集成C++模块等,而且还可以使用大量的NPM包;
Electron内置的Native API解决了跨平台的问题,提供了统一的原生界面,比如像窗口、托盘,其次是系统能力,比如Notification,最后是应用的基础能力,比如像软件更新、崩溃监控等等。
四、Electron的历史
Electron的历史得从浏览器的历史讲起。
1989年,英国科学家伯纳斯-李(Berners-Lee)发明了万维网,然后在90年他写出了世界上第一个浏览器。就是Nexus,但当时这个浏览器有一个很大的缺陷就是不能显示图片。
然后到了1993年,NSCA(美国国家超级电脑应用中心)研发了第一款能看到图片的浏览器,这款浏览器叫做Mosaic(马赛克)。
1994年,Mosaic的核心成员Marc Andreessen,他跟辞职的硅谷制图(Silicon Graphics)创始人吉姆.克拉克一起创建了网景公司,他们的愿望是打破Mosaic的垄断地位,起初它们取了一个名字“Mozilla”(原因有二,Mosaic Killa, Godzilla eat the Mosaic),因为市场的原因最后还是用了Netscape。
随着网景浏览器的快速发展,在1995年微软发现浏览器的巨大市场之后,推出了IE1,也就是这一年,网景公司找来了天才程序员布兰登.艾奇,他用10天时间创造了JavaScript;但微软还是有钱,迭代速度很快,通过操作系统的垄断以及捆绑销售,逐步拿下了市场份额。
1998年网景被击败,受Linux开源项目的影响,网景公司决定开放源码以回击IE,转型为开源软件,名为Mozilla,在收购之前成立了Mozzila非盈利组织。
到了2002年在网景源码的基础上派生了火狐,它在安全、插件扩展、开发调试工具等方面都有着巨大的贡献,然后到了2008年,基于Firefox开发的Chrome诞生了,它是非常具有颠覆意义的,重新设计后带来了极致的简洁,然后引入了多进程带来的稳定,还有带来了10倍提速的V8引擎。对应Chrome也有一份开源项目就是Chromium。
随后在2009年,Ryan Dahl基于V8引擎将非阻塞IO和JS整合,让JS延伸到了服务端领域。有了Chromium,V8 Node.js开源后,终于有人开始尝试JS来做桌面端的应用,在2011年英特尔工程师王文睿写了第一版node-webkit(NW基于Node.js和Chromium),当时还是一个默默无闻的项目,2012年他招来了一个实习生做这个项目,实习生一人兼顾了开发、维护、宣传,接近重写了NW,将NW做到了Github C++前五,这位实习生就是Electron的作者赵成。赵成在2012年年底加入Github的Atom项目组,他尝试用NW开发,发现问题太多,响应太慢,在2013年的时候终于决定要开发Atom-shelll,然后在2015年正式改名为Electron。
五、怎么判断一个项目是否是用Electron开发的?
以VS Code举例,通过如下方式就可得知。
六、开发Electron与开发Web开发有什么不同
主要体现在四个方面:
第一,主进程与渲染进程。
第二,进程间通信。
第三,需要用到很多原生能力。
第四,可以较大程度上释放前端的想象力,能做的事情更多。
具体来说:
1、主进程和渲染进程
1)主进程
Electron运行package.json的main脚本的进程称为主进程。
每一个应用只有一个主进程。
主进程管理着原生GUI,典型的窗口(BrowserWindow、Tray、Dock、Menu)。
主进程还负责创建渲染进程。
主进程还控制着应用的生命周期(app)。
主进程的模块有:
- app
管理了应用的生命周期,比如说退出;同时它又可以设置app本身的一些属性,比如说Dock。例如app.on('ready', callback)
- BrowserWindow
用来管理窗口
- ipcMain
是和ipcRenderer进行IPC通信的。
- Menu
- Tray
- MenuItem
- dialog
- Notification
用来做一些可交互的通知
- webContents
用来加载具体的页面
- autoUpdater
是更新模块
- globalShortcut
用来设置全局的快捷键
-
systemPreferences
-
TouchBar
-
netLog
-
powerMonitor
-
inAppPurchase
-
net
-
contentTracing
-
BrowserView
-
session
-
protocol
-
Screen
-
clipboard
用来读写剪切板
- crashReporter
用来监控主进程和渲染进程是否有崩溃
- shell
- nativeImage
这是一些原生的GUI
clipboard、crashReporter、shell、nativeImage这四个模块是主进程和渲染进程都可以调用。
2)渲染进程
展示Web页面的进程称为渲染进程。
通过Node.js以及Electron提供的API可以跟系统底层打交道。
一个Electron应用可以有多个渲染进程。
主进程的模块有:
-
ipcRender 是和ipcMain进行IPC通信的
-
remote
用来调用主进程的模块,但是建议大家不要使用这个模块
- desktopCapture
用来捕获桌面流,通过它可以进行系统的截图和获取到屏幕的视频流等等。
- webFrame
- nativeImage
- shell
- crashReporter
用来监控主进程和渲染进程是否有崩溃
- clipboard
用来读写剪切板
总结一下,主进程和渲染进程的模块如下:
2、进程间通信
1)Electron进程间通信的目的
- 通知事件
比如,我们想在页面上创建一个原生菜单,但是Electron中只有主进程能够创建原生菜单,这时就需要用到进程间通信,通知主进程去创建原生菜单
- 数据传输
比如,我想在页面中获得系统的内存情况,这时就需要将这些数据通过IPC来传输。
- 共享数据
比如,我们想让用户信息在不同的进程中都能够看到,这个时候就需要用到IPC来共享数据。
2)IPC通信模块
Electron提供了IPC通信模块,主进程的ipcMain和渲染进程的ipcRenderer。
ipcMain和ipcRenderer都是EventEmitter对象。
3)三种类型的进程间通信
- 从渲染进程到主进程
有两种写法:
第一种,callback写法:
ipcRenderer.send(channel, ...args)
const {ipcRenderer} = require('electron);
ipcRenderer.send('do-some-work', 1, 2);
ipcMain.on(channel, handler)
const {app, BrowserWindow, Notification, ipcMain} = require('electron');
let win;
app.on('ready', () => {
win = new BrowserWindow({
width: 300,
height: 300,
webPreferences: {
nodeIntegration: true
}
});
win.loadFile('./index.html');
handleIPC();
});
function handleIPC() {
ipcMain.on('do-some-work', function(e, a, b) {
console.log('do-some-work', a ,b);
})
}
第二种,Promise写法(Electron 7.0之后,处理请求 + 响应模式)。
ipcRenderer.invoke(channel, ...args)
ipcMain.handle(channel, handler)
- 从主进程到渲染进程
ipcRenderer.on(channel, handler)
const {ipcRenderer} = require('electron');
ipcRenderer.on('do-some-work', () => {
alert('do-some-work');
})
webContents.send(channel)
const {app, BrowserWindow. Notification, ipcMain} = require('electron');
let win;
app.on('ready', () => {
win = new BrowserWindow({
width: 300,
height: 300,
webPreferrences: {
nodeIntegration: true
}
});
win.loadFile('./index.html');
setTimeout(handleIPC, 500);
})
function handleIPC(){
win.webContents.send('do-some-work');
}
- 页面间(渲染进程与渲染进程间)通信
通知事件:
通过主进程转发(Electron 5之前);
ipcRenderer.sendTo(Electron 5之后)。
数据共享:
Web技术(localStorage、sessionStorage、indexedDB);
使用remote:它会将数据挂在一个全局的过程中,但不太建议使用remote这个模块,因为用得不好的话会导致程序卡顿,影响性能
例子:
// main.js
const {app, BrowserWindow, Notification, ipcMain} = require('electron');
let win;
let win2;
app.on('ready', () => {
win = new BrowserWindow({
width: 300,
height: 300,
webPreferences: {
nodeIntegation: true
}
});
win2 = new BrowserWindow({
width: 300,
height: 300,
webPreferences: {
nodeIntegation: true
}
});
win2.loadFile('./index.html');
gloabal.sharedObject = {
win2WebContentsId: win2.webContents.id
};
setTimeout(handleIPC, 500);
})
// renderer.js
const {ipcRenderer, remote} = require('electron');
let sharedObject = remote.getGlobal('sharedObject');
let win2WebContentsId = sharedObject.win2WebContentsId;
ipcRenderer.sendTo(win2WebContentsId, 'do-some-work', 1);
// renderer2.js
const {ipdRenderer} = require('electron');
ipcRenderer.on('do-some-work', (e, a) => {
alert('renderer2 handle some work' + a);
})
- 进程间通信的一些经验
少用remote模块,每次会触发底层的同步IPC事件,特别影响性能,甚至如果处理不好的话,进程就会卡死;
不要用sync模式,一旦处理不好,整个应用就会卡死;
在请求+响应的通信模式下,需要自定义超时时长限制,当超时时要response一个超时异常事件,让业务去处理。
3、需要用到很多原生能力
1)Electron的原生能力主要是源于两个方面:Electron内置的Native API以及强大的Node.js。
Electron内置的API提供的原生能力:
一方面,是使用Electron API创建原生的客户端GUI,包括:
-
BrowserWindow应用窗口
-
Tray托盘
-
app设置dock.badge
-
Menu菜单
-
dialog原生弹框
-
TouchBar苹果触控栏
-
……
基于它们可以设置右键菜单、窗口定制、系统托盘、在Dock上设置未读消息数等。
另一方面,是使用Electron API获得底层的能力,包括:
-
Notification
-
clipboard 读写剪切板
-
globalShortcut 注册全局快捷键
-
desktopCapture 捕获桌面流
-
shell 打开本地文件夹、本地文件、本地URL
-
……
基于它们在桌面环境集成系统通知、剪切板、系统快捷键、文件拖放等,也可以做电源监视、内存、CPU、屏幕获取等。
强大的Node.js提供的原生能力,这一点不言而喻,在此不再赘述。
2)Electron可获得的原生能力
第一,基于原生API,可获得:
- 文件读写(通过fs)
- 操作系统(通过child_process调用系统的Shell命令)
- 加解密(通过crypto)
Electron同时在主进程和渲染进程中对Node.js暴露了所有的接口。
第二,基于Node.js可集成第三方模块:
- 通过npm安装即可引入社区上所有的Node.js库
包括在渲染进程中,也是可以直接使用Node.js模块的
- Node.js add-on:用Node.js的插件机制可以去集成C++写的模块
- node-ffi(Foreign Function Interface):通过node-ffi可以去集成C++写好的动态库,比如对于打印这一动态库的集成。
第三,使用Node.js调用系统集成好的一些能力:
- 调用Windows RT(通过:github.com/NodeRT/Node… APIs的Node.js模块生成器),比如通过它可以调用蓝牙、USB、预览文件等。
备注:Windows RT是Windows家族的一个新成员,新系统画面与操作方式变化极大,采用全新的Modern UI风格用户界面,各种应用程序、快捷方式等能以动态方块的样式呈现在屏幕上,用户可自行将常用的浏览器、社交网络、游戏、操作界面融入。Windows RT专注于ARM平台,并不会单独零售,仅采用预装的方式发行。Windows RT 中将包含针对触摸操作进行优化的微软 Word、Excel、PowerPoint 和 OneNote 的桌面版,但与旧版Windows应用不兼容,可通过WinRT开发环境为其创建Modern UI应用。
Windows RT是ARM平台下的独立版本,无法单独购买,只能预装在采用ARM架构处理器的PC和平板电脑中。Windows RT无法兼容X86软件,但将附带专为触摸屏设计的微软Word、Excel、PowerPoint和OneNote。
- 在MacOS上调用AppleScript(通过github.com/TooTallNate… OS X上轻松执行任意AppleScript代码的模块,通过它可以调用系统的原生应用,做一些跟系统的原生应用交互的事情。
总的来说,Electron的原生能力可以总结成下表:
4、释放前端想象力:基于Electron能做什么?
1)无兼容问题
-
不用担心IE、Safari上的表现差异了
-
大量使用Chrome已支持的新的feature
比如,在Chrome77版本开始,就支持了原生的lazy-loading(developers.google.cn/web/updates…
<img src="image.jpg" loading="lazy" width="400" height="250" alt="...">
怎么知道Chrome有什么新特性呢?看这个网址就好了,一般每个月会更新一个版本:developers.google.cn/web/updates
- Babel中设置targets为Electron对应的Chrome版本,包的体积也会被缩减。
2)可以使用ES6/7/8/9/10等的最新语法
-
Async、Await、Promise
-
String、Array、Object等的一些高级用法
例如,'123'.padStart(5, '0')
- BigInt数据类型
例如,BigInt(12345678901234567890123456789)
3)无跨域问题
- 可以使用Node.js发送请求
- 也可以使用Electron net发送请求
都不会被浏览器的跨域请求所影响,而且可以做到请求的时候少一个option请求,也不会被浏览器同域名6个请求所限制住。
4)更多精彩
- 操作本地文件
- 会有一份本地日志,方便我们排查问题
- 引入一些更好用的本地DB,如Lowdb、Leveldb甚至是SQLite等等,而不局限于IndexDB
- 可以通过Node.js的worker_threads和child_process将任务拆成多线程、多进程并行,充分利用计算机的多核
七、其它
1、如何运行Electron项目
npx electron main.js
2、怎么打开调试面板
方法有二:
1)通过代码:someWindow.webContents.openDevTools()
2)通过顶部菜单:View——>Toggle Developer Tools