关于electron
Electron 是一个使用 JavaScript, HTML 和 CSS 等 Web 技术创建原生程序的框架。它完全兼容 Mac、Windows 和 Linux,真正实现了跨平台的桌面端应用解决方案。
技术架构
Electron的核心技术架构是由 Chromium + Node.js + Native APIs 组成的。
接下来,我们简单介绍一下它的三大核心武器:
- 首先是 Chromium,我们可以把它理解为是一个拥有最新版浏览器特性的一个 Chrome 浏览器,它带给我们的好处就是在开发过程中无需考虑浏览器的兼容性,我们可以使用一些 ES6、ES7 最新的语法,可以放心的使用 Flex 布局,以及浏览器的最新特性,都可以尝试,不需要考虑兼容性的问题。
- Node.js 则是提供了一个文件读写、本地命令调用、以及第三方扩展的能力,并且基于 Node.js 整个强大的生态,将近几十万的 Node.js 模块都可以在整个客户端内使用。
- Native APIs 提供了一个统一的原生界面的能力,还包括一些系统通知、快捷键,还可以通过它来获取一些系统的硬件信息。还提供了桌面客户端的基础能力,像更新机制、崩溃报告这样的能力。
Chromium和chrome浏览器的区别
Chromium是google开源的浏览器项目,由开源社区维护,它支持Windows、Mac、Linux等多种操作系统,国内的大多数双核浏览器都是基于它进行开发的。
Chrome浏览器也是基于Chromium进行的二次开发。在Chromium的基础上,chrome提供了额外的高阶功能:
- 对特殊音频格式的支持,如AAC, H.264和MP3编码
- 内置Flash插件
- 自动更新: Chrome的Windows和Mac用户可获得额外的后台应用,可自动让Chrome保持最新版本
- 扩展限制:对于Chrome,Google会停用未在Chrome网上应用商店中托管的扩展程序。
- 崩溃和错误报告:Chrome用户可以选择将有关崩溃和错误的统计信息发送给Google进行分析。
快速开始
安装electron应用
可以参考官方文档-打造你的第一个electron应用,大家也可以直接copy下面的代码在命令行执行,就可以立马体验一个electron应用的demo了。
git clone https://github.com/electron/electron-quick-start
cd electron-quick-start
npm install
npm start
引入react
渲染层面的技术架构你可以选择自己需要的,不一定是react,也可以vue、angular等,这里我以react为例子,这里直接用react的官方脚手架即可。
npx create-react-app electron-quick-start
cd electron-quick-start
npm start
我们把react的脚手架也安装在了electron的目录里面,因此需要做些调整和改动。首先需要对electron项目和react项目的两个package.json进行合并,将启动electron的命令改为npm run electron;其次是将electron的入口文件main.js里面加载视图的文件路径改为http://localhost:3000/,main.js的部分代码如下:
const isDev = require('electron-is-dev')
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})
if(isDev){
mainWindow.loadURL('http://localhost:3000/') // 这里改为react的启动目录
} else {
mainWindow.loadFile(path.join(__dirname, '/../build/index.html')) // 加载打包后的html
}
}
至此,我们就可以愉快的在electron项目中使用react了。显而易见,这里的缺点是需要同时启动两个命令,你如果想要一个命令启动,安装对应的工具库即可。
当然,如果要在正式项目中使用,可以安装 electron-forge,这是一个成熟的脚手架,集成了打包、发布功能,还可以选择模板(如React、Vue、Angular 等)作为渲染层框架。
进程间通信
要了解什么是进程间通信,首先要了解electron中的两个重要的概念,就是关于主进程和渲染进程。
主进程
- Electron中运行
package.json
中的main
脚本的进程被称为主进程,即main.js就是运行在主进程。 - 一个electron应用有且只有一个主进程。
- 只有主进程可以直接进行GUI相关的原生API操作。
渲染进程
- 运行在Chromium的web页面姑且叫渲染进程,即运行index.html的环境就是渲染进程。
- 一个electron应用可以有多个渲染进程。
- 渲染进程在引入Node.js 模块的前提下,可以在页面中和操作系统进行一些底层交互(如fs模块)。
如何通信
知道什么是主进程和渲染进程以后,接下来就介绍一下主进程和渲染进程之间是如何通信的呢?
主进程和渲染进程之间是通过ipcRenderer 和 ipcMain 模块通信的。具体API文档可以参考官方示例,这里举一个渲染进程向主进程通信的例子。
举例:页面中有一个textarea输入框,用户输入内容以后点击“保存到本目录”,即可保存输入框内容到本目录的msg.txt文件夹中。
这样一个简单的通信过程就完成了,当然主进程也可以主动向渲染进程通信,以及渲染进程之间的通信,这里不再赘述,原理也是类似的。
打包
打包是开发桌面端应用最后一步,也是必不可少的一步,目前市面上比较常用的electron打包工具有两种,electron-packager 和 electron-builder,我们项目中采用是比较简单的第一种打包工具。
electron-packager
这个打包工具的特点如下:
- 可以直接生成
.app
,.exe
等可执行的文件,用户无需安装,打开即可使用 - 配置简单,通常一句命令行就可搞定
下面是一个例子,package.json的部分代码:
"scripts": {
"start": "electron .",
"packageOS": "electron-packager . DMS企业版 --platform=mas --arch=x64 --icon=dms --out=./dist --asar --app-version=1.0.0",
"packageWin64": "electron-packager . 'DMS企业版 --platform=win32 --arch=x64 --icon=dms --out=./dist --asar --app-version=1.0.0",
"packageWin32": "electron-packager . DMS企业版 --platform=win32 --arch=ia32 --icon=dms --out=./dist --asar --app-version=1.0.0"
},
具体的参数含义大家可以参考开发文档,需要注意的是不同平台打包所需要的图片格式也是不一样的,mac的直接是png格式的图片就可以,而windows的是icns格式图片。
electron-builder
electron-builder不仅可以打包为可执行文件,还可以打包为可安装程序,功能与electron-packager相比也要丰富一些,所以打包的配置也是更为繁琐。从github数据来看 electron-builder 比 electron-packager 多2000+颗星,由此可见electron-builder应用会更广泛一些。
热更新
CDN资源更新
在某些场景下(如:一般在web页面开发的时候我们的静态资源都是CDN化的,为了和web共用一套代码,我们可以在APP端直接引用这些静态资源,另外就是增量更新的场景),我们的UI视图层代码是托管在CDN上的,为了实现这时候如果用户一直不重启或者刷新APP,那么这些静态资源也是不会主动更新的;这个时候我们常见的做法是通过轮询调用接口或者服务端推送,来获取是否更新的通知,如果发现有更新,则弹窗提醒用户,让用户重载整个页面,达到刷新的目的。
应用包更新
除了上面CDN的情况,还有一种情况是所有的资源都被打包在了APP,这个时候如果系统有更新要怎么办呢?
此时要分两种情况,一是能够直接使用update.electronjs.org的情况,另外一种是使用自己的更新服务器。
1)使用 updata.electronjs.org 更新
能够直接使用该工具库的前提是:
- 应用运行在 macOS 或者 Windows
- 应用有公开的 GitHub 仓库
- 编译的版本发布在 GitHub Releases
- 编译的版本已代码签名
在具备了该前提的情况下直接安装update-electron-app使用即可
npm install update-electron-app
从你的应用的 main process 文件调用这个更新:
require('update-electron-app')()
默认情况下,这个模块会在应用启动的时候检查更新,然后每隔十分钟再检查一次。 当发现了一个更新,它会自动在后台下载。 当下载完成后,会显示一个对话框以允许用户重启应用。
2)部署更新服务器
如果你开发的是一个私有的 Electron 应用程序,或者你没有在 GitHub Releases 中公开发布,你可能需要运行自己的更新服务器。
根据你的需要,你可以从下方选择:
- Hazel – 用于私人或开源应用的更新服务器,可以在 Now 上免费部署。 它从GitHub Releases中拉取更新文件,并且利用 GitHub CDN 的强大性能。
- Nuts-同样使用GitHub Releases, 但得在磁盘上缓存应用程序更新并支持私有存储库。
- electron-release-server – 提供一个用于处理发布的仪表板,并且不需要在GitHub上发布发布。
- Nucleus – 一个由Atlassian维护的 Electron 应用程序的完整更新服务器。 支持多种应用程序和渠道; 使用静态文件存储来降低服务器成本。
更新服务器部署好以后,你就可以直接调用electron的 autoUpdater 模块进行更新通知了
const { app, autoUpdater, dialog } = require('electron')
// 构建更新服务器的URL并且通知autoUpdater
const server = 'https://your-deployment-url.com'
const url = `${server}/update/${process.platform}/${app.getVersion()}`
autoUpdater.setFeedURL({ url })
// 轮询检查更新
setInterval(() => {
autoUpdater.checkForUpdates()
}, 60000)
检测到更新后通知用户代码:
// 成功通知
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
const dialogOpts = {
type: '消息',
buttons: ['立即重启', '稍后再试'],
title: '更新通知',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version has been downloaded. Restart the application to apply the updates.'
}
dialog.showMessageBox(dialogOpts).then((returnValue) => {
if (returnValue.response === 0) autoUpdater.quitAndInstall()
})
})
// 失败通知
autoUpdater.on('error', message => {
console.error('There was a problem updating the application')
console.error(message)
})
更多内容你也可以参考官方文档更新应用程序部分。
参考文档:
https://www.electronjs.org/docs
https://github.com/electron
https://cnodejs.org/topic/57812e64ee5f048d54f90800
https://www.electronjs.org/docs/tutorial/first-app#%E6%89%93%E9%80%A0%E4%BD%A0%E7%9A%84%E7%AC%AC%E4%B8%80%E4%B8%AA-electron-%E5%BA%94%E7%94%A8