本文由 Deguang 发表于 码路-技术博客
Tips:
- Electron 介绍
- Electron 环境搭建
- 进程通信
- 调用系统 API
Write once, run anywhere.
Sun 公司 Java 介绍词。
端的跨平台实现方案有哪些?
- Web(浏览器)
- 移动端设备:Hybrid(混合)、React Native、Weex、Flutter
- 桌面端:NW.js、Electron、Flutter(~1.0)
Electron
1. 什么是 Electron
Electron 是由 Github 开发,用 HTML,CSS 和 JavaScript 来构建跨平台桌面应用程序的一个开源库。 Electron 通过将 Chromium 和 Node.js 合并到同一个运行时环境中,并将其打包为 Mac,Windows 和 Linux 系统下的应用来实现这一目的。开发者只要使用 Web 技术完成业务部分即可,这就是对前端开发者最友好的地方。
2. Electron 应用结构
Elctron 应用运行时,分为 主进程
和 渲染进程
。
主进程 (Main Process)
-
package.json
中定义的main
脚本运行的进程,被定义为主进程
,一个 Electron 应用有且只有一个主进程。 - 主进程可以创建 Web 页面窗口,并传入 URL 加载网页作为图形界面。
渲染进程 (Renderer Process)
- Electron 的每个页面都有它自己的进程,叫做渲染进程。每一个渲染进程都是独立的,只关心它所运行的页面;
进程通信(IPC, Inter-Process Comminication)
Electron 不允许渲染进程调用系统 GUI 的原生 API,例如打开文件选择之类的系统操作,这种对系统 API 的调用只允许存在与主进程中。渲染进程,也就是页面调用 系统 API,需要由主进程担任桥梁的作用,来完成操作并得到返回结果。这里有两种方式可以实现进程通信:
使用 ipcRenderer 和 ipcMain 模块通信
- ipcRenderer
ipcRenderer 是从渲染进程到主进程的异步通信,可以使用它提供的一些方法从渲染进程发送同步或异步的消息
- ipcMain
ipcMain 是从主进程到渲染进程的异步通信,处理从渲染进程发送出来的异步和同步信息,
// renderer process
const {ipcRenderer} = requier('electron')
// async
ipcRenderer.on('PICK_FILE_CALLBACK', (event, arg) => {
console.log(arg) // files
})
ipcRenderer.send('PICK_FILE')
// sync
ipcRenderer.sendSync('PICK_FILE_SYNC') // files
// main process
const {ipcMain} = require('electron')
// async
ipcMain.on('PICK_FILE', (event, data) => {
// do something ...
event.sender.send('PICK_FILE_CALLBACK', 'files')
})
// sync
ipcMain.on('PICK_FILE_SYNC', (event, data) => {
// do something
event.returnValue = 'files'
})
more: ipcRenderer、 ipcMain
-
ipcMain
、ipcRenderer
又是什么?
ipcMain 和 ipcRenderer 都是 EventEmitter 类的一个实例。 EventEmitter 类是由 NodeJS 中的 events 模块定义、导出的。EventEmitter 类是 NodeJS 事件的基础,实现了事件模型需要的接口, 包括 addListener,removeListener, emit 及其它工具方法. 同原生 JavaScript 事件类似, 采用了发布/订阅(观察者)的方式, 使用内部 _events 列表来记录注册的事件处理器。
使用 remote 进行 RPC 通信
在渲染进程中使用主系统模块。
// 渲染进程中
const { BrowserWindow } = require('electron').remote
let win = new BrowserWindow({width: 600, height: 400})
win.loadURL('https://github.com')
- remote 对象
remote 模块返回的对象表示主进程中的一个对象,调用远程对象、远程函数时,相当于发送同步进程信息。let win = new BrowserWindow({width: 600, height: 400})
,相当于在主进程中创建了一个 BrowserWindow 对象,然后在渲染进程中返回了相应的远程对象。
more: remote
3. API
Electron API
Electron 提供了大量 API 以优化桌面应用开发体验。
Electron API 都有指派进程类型(文档中标记):只能用于主进程(BrowserWindow
)、只能用于渲染进程(remote
) 和 两种进程中均可使用。
Node.js API
Electron 同时在主进程和渲染进程中对Node.js 暴露了所有的接口
- 原生 API
// Native API
const fs = require('fs')
fs.readFile(...)
- 第三方 Node.js 模块
npm install -save axios
const axios = require('axios')
axios.interceptors.request(...)
4. 第一个 Electron 应用
环境依赖:Node.js
&& Npm
(Yarn
)
- Node.js: 安装参考 https://nodejs.org
- Yarn:
npm i -g yarn
推荐使用yarn
构建 Electron,使用npm
大概率出现依赖安装失败的情况
起步
0.0.1 创建 demo
目录,执行 npm init
,配置启动脚本 "start": "electron ."
// package.json
{
"name": "demo",
"version": "1.0.0",
"description": "",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"author": "",
"license": "ISC"
}
0.0.2 创建 main.js
&& index.html
➜ demo tree
.
├── index.html
├── main.js
└── package.json
0.0.3 安装 Electron
npm install --save-dev electron
0.0.4 创建一个窗口:
// main.js
const { app, BrowserWindow } = require('electron')
let win
function createWindow() {
win = new BrowserWindow({ width: 600, height: 400})
win.loadFile('index.html')
}
app.on('ready', createWindow)
Hello, Electron.
Node.js: ;
Chrome: ;
Electron: .
0.0.5 执行 npm run start
,即可打开一个窗口,显示 Hello, Electron.
。
0.0.6 更新main.js
,尝试更多功能:
// main.js
const { app, BrowserWindow } = require('electron')
let win
function createWindow() {
win = new BrowserWindow({ width: 600, height: 400})
win.loadFile('index.html')
win.webContents.openDevTools()
win.on('close', () => {
// 关闭窗口、清空 win 对象
win = null
})
app.on('window-all-closed', () => {
// macOS 应用通常关闭窗口还是保活的,只有使用 cmd + q 强制退出
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
// macOS 点击 dock 图标并且没有其他窗口打开时,重新创建一个窗口
if (win === null) {
createWindow()
}
})
}
app.on('ready', createWindow)
0.0.7 重新执行 npm run start
启动应用。
more: 更多 Electron API 使用,可以尝试官方 electron-api-demos
打包应用
electron-packager
# 安装 electron-packager
npm install electron-packager --save-dev
# 基本命令
electron-packager --platform= --arch= [optional flags...]
# 例如:
# electron-packager ./ demo --out ./dist --app-version 1.0.0 --overwrite
参数说明:
- sourcedir:项目路径
- appname:应用名称
- platform:构建平台的应用(Windows、Mac 还是 Linux)
- arch:x86、 x64 还是两个架构都用
- optional options:可选选项
为了更方便的构建,在 package.json
增加构建脚本
"package": "electron-packager ./ demo --out ./dist --app-version 1.0.0 --overwrite"
执行 npm run package
more: electron-packager
electron-builder
# 安装 electron-builder
npm install electron-builder --save-dev
// package.json 增加如下配置
"build": {
"productName": "xxx",
"appId": "com.xxx.xxx"
},
"scripts": {
"dist": "electron-builder"
}
执行 npm run dist
,完成打包
more: electron-builder
ps:mac 跨平台 打包 win32 需要
wine
客户端数据库
Electron 应用可以在本地使用客户端数据库,来维护本地数据,进行相应的 CURD
操作,下面是常用的一些轻量级数据库:
- nedb
- sqlite
- Rxdb
- ...
参考文档:
- Electron 文档