Electron 介绍
作为一名热衷于新技术的前端开发工程师,如果你一直期望着打造一款桌面应用,又不希望付出太多的精力花费在 C++、.NET 等技术上,那么使用 Electron 这种低成本的技术来开发跨平台的桌面应用对我们来说性价比是非常高的,从而快速地点亮桌面应用开发的技能点。
Electron 是一个基于 V8 引擎和 Node.js 的开发框架,允许用 JavaScript 开发跨平台(Windows、Mac OS X 和 Linux)桌面应用。用 Electron 开发的应用有很多,如 Visual Studio Code、Atom、支付宝小程序 IDE(蚂蚁开发者工具)等。
整体架构概览
Electron 主要包含两类进程,主进程(Main Process)和渲染进程(Renderer Process)。当我们在启动一个 App 时,那么会先启动主进程,主进程会启动应用并创建 native UI,随后会在 native UI 上启动一个或多个的 browser window 即 web pages,每一个 BrowserWindow 都是一个渲染进程 。在 native UI 上的不同的 browser windows 它们是独立的沙箱环境,不同的进程之间是互相隔离的,Electron 提供了几种进程之间通信的方式,比如 IPC(inter-process communication)和 RPC(remote-process communication)。
主进程(Main Process)和渲染进程(Renderer Process)
Main Process
Electron 运行 package.json 的 main 脚本(程序的入口)的进程被称为主进程,一个应用只有一个主进程,主进程可以:
- 主进程包含了 Chromium 和 Node 的运行时环境;
- 主进程可以通过实例化 BrowserWindow 展示 Web 页面,每一个 Web 页面都会运行在它自己的 渲染进程 中;
- 主进程可以访问原生的 API(注册快捷键、创建菜单栏等),如果渲染进程需要访问原生 API,那么需要和主进程进行通信,请求主进程来进行相关的调用,再返回给渲染进程;
- 主进程可以管理所有的 Web 页面和其对应的渲染进程。
Renderer Process
渲染进程主要是用来渲染 Web 页面,并且兼容传统的 Web 页面,支持所有的 DOM API、Node API。除此之外,渲染进程还可以通过和主进程通信来访问原生的 API。
常用模块的介绍
Electron 提供的模块也是按照主进程和渲染进程来进行划分,不能的模块只能在其对应的进程使用,下面介绍几种常用到的模块。
app 模块
app 模块在主进程中使用。用来控制整个应用程序的事件生命周期,常见的几种监听事件有 ready、before-quit、will-quit。
const {app} = require('electron')
app.on('ready', ()=>{
console.log('当 Electron 完成初始化时被触发')
})
app.on('before-quit', (e)=>{
// 可以调用 e.preventDefault() 来阻止默认的行为(即关闭应用程序)
console.log('在应用程序开始关闭窗口之前触发')
})
app.on('will-quit', (e)=>{
// 可以调用 e.preventDefault() 来阻止默认的行为(即关闭应用程序)
console.log('在所有的 Web 窗口关闭,应用程序即将退出时触发')
})
BrowserWindow 模块
BrowserWindow 模块在主进程中使用。用来创建管理浏览器窗口,并且可以控制窗口的大小、边框、标题栏样式等。
const {app} = require('electron')
const isDev = require('electron-is-dev')
const path = require('path')
let win
const createWindow = () => {
win = new BrowserWindow({
show: false, // 先不显示 Web 页面,等加载后在显示
webPreferences: {
nodeIntegration: true // Web 集成 node 环境
},
titleBarStyle: 'hiddenInset' //设置标题栏样式,隐藏标题栏, 显示小的控制按钮在窗口边缘
})
win.maximize() //打开后自动最大化窗口
win.loadURL(isDev
? 'http://localhost:3000/'
: `file://${path.join(__dirname, './index.html')}`)
if (isDev) {
win.webContents.openDevTools();
}
win.once('ready-to-show', () => {
win.show()
})
}
app.on('ready', createWindow) // 监听 app 启动后,创建 BrowserWindow 打开 Web 页面
关于 BrowserWindow 的更多配置项参考:
https://www.electronjs.org/docs/api/browser-window#new-browserwindowoptions
ipcMain、webContents 模块
ipcMain 模块在主进程中使用。用来处理从渲染进程(Web 页面)发送出来的异步和同步信息,处理完后,也可以同步或异步将数据返回给渲染进程。
const {ipcMain} = require('electron')
// 监听由渲染进程发送过来的事件,事件名称是'renderer-process-message-listener',发送的数据是 data
ipcMain.on('renderer-process-message-listener', (event, data) => {
const backData = 'data'
event.returnValue = backData // 回复同步信息给渲染进程
event.reply(backData) // 回复异步信息返回给发送过来的这个渲染进程
event.sender.send(backData) // 回复异步信息给主窗口这个渲染进程
})
webContents 模块也是用于主进程中。ipcMain 主要是用来处理由渲染进程发送过来的事件,而 webContents 则是用来由主进程主动往渲染进程中发送事件:
win = new BrowserWindow()
win.webContents.send('event-name', {data:'data'}) // 在主进程中使用,调用 browserWindow 的 send 方法进行发送事件
ipcRenderer 模块
在渲染进程中,主要用到的就是 ipcRenderer 模块,用于在渲染进程(Web 页面)中发送同步或异步消息到主线程,也可以接收由主进程回复的消息:
const { ipcRenderer } = require('electron')
// 在渲染进程中主动往主进程中发送消息 ipcRenderer.sendSync 同步发送,ipcRenderer.send 异步发送
const backData = ipcRenderer.sendSync('synchronous-msg', {data:'data'})
ipcRenderer.send('asynchronous-msg', {data:'data'})
ipcRenderer.on('main-process-msg-listener', (event, data) => {
})
脚手架的搭建
下载脚手架
1. 下载:
git clone https://github.com/Aceysx/electron-startup.git
2. 安装项目依赖:(在项目根目录下)
npm install
3. 启动:(在项目根目录下)
electron app/main //启动 app
npm start // 启动 web
Web 页面启动成功后,刷新 App 窗口(Ctrl/cmd+r)加载 Web 页面,即可以看到下面的页面:
脚手架的介绍
本 Chat 主要是为了介绍 Electron,所以为了更加方便轻松地创建用户交互界面、设计简洁的数据状态,脚手架集成了 React、Redux 和 Ant Design UI 帮助快速开发。
如果读者对 React 不熟悉,也可以使用相应的库替换,或者直接使用 HTML/CSS/JavaScript。后续讲解中涉及的 React、Redux 的相关内容时也会做相应的的说明。
启动、调试
在启动成功后,可以看到带有调试控制台的 App 页面,是不是很熟悉,和我们平时开发调试 Web 页面一样:
来看看脚手架都做了什么。
目录结构
electron-startup
-- app
---- main.js
-- public
---- index.html
-- src
---- ui
---- index.js
-- package.json