基础
核心技术:Chromium + Node.js + Native APIs
- Chromium: 是 Google 为发展 Chrome 浏览器而启动的开源项目,Chromium 相当于 Chrome 的工程版或称实验版,新功能会率先在 Chromium 上实现,待验证后才会应用在Chrome 上
- Node: 是一个让 JavaScript 运行在服务端的开发平台,Node 使用事件驱动,非阻塞I/O 模型而得以轻量和高效。
- Native API: 为了提供原生系统的GUI支持,Electron内置了原生应用程序接口,对调用一些系统功能,如调用系统通知、打开系统文件夹提供支持。
本质:Web项目包了一层Node环境的壳子
优点
- 开发效率高
- 执行效率高
- 无需考虑兼容性问题
- 基于JavaScript生态
- Electron 可以使用操作系统接口
缺点
- 打包后的应用体积巨大
- 开发复杂度较大
- 安全性问题
- 资源消耗较大
- 版本发布过快
优势
- 用户角度: 客户端是一款独立的软件,其综合体验一般都是比网站高的,尤其是涉及到「工具」范畴的应用,此外,特定的用户群体也会有类似的使用习惯
- 发行方角度: 客户端是另一种产品形式,是一种产品的分发方式和入口,客户端可以实现很多本地应用独有的需求去触达用户,也能提供更加可靠的服务
- 开发角度: 不用考虑浏览器兼容,Chromium 也足够开发使用一些先进的 CSS 或 JS 特性,跳出了浏览器的沙盒,可以自己去控制 Electron 中的 [ 浏览器 ],社区生态好
主进程和渲染进程
主进程 (Main进程)
每个 Electron 应用都有一个单一的主进程,是每个 Electron 应用的入口文件。它控制着整个 App 的生命周期,从打开到关闭。 它也管理着系统原生元素比如菜单、菜单栏、Dock 栏(软件启动后,在屏幕下方生成的一条栏)和托盘等。主进程在 Node.js 环境中运行,这意味着它具有 require 模块和使用所有 Node.js API 的能力。
主进程文件都在 package.json 中的 main 属性中指定。
在主进程运行的脚本可以以创建 web 页面的形式展示 GUI。创建窗口等所有系统事件都要在主进程中进行。
主进程的主要目的是使用 BrowserWindow 模块创建和管理应用程序窗口。
渲染器进程 (Rendererer进程)
每个 Electron 应用都会为每个打开的 BrowserWindow ( 与每个网页嵌入 ) 生成一个单独的渲染器进程。 洽如其名,渲染器负责 渲染 网页内容。 所以实际上,运行于渲染器进程中的代码是须遵照网页标准的 (至少就目前使用的 Chromium 而言是如此) 。
渲染器无权直接访问 require 或其他 Node.js API。 为了在渲染器中直接包含 NPM 模块,您必须使用与在 web 开发时相同的打包工具 (例如 webpack 或 vite)
创建一个 web 页面都会创建一个渲染进程。每个 web 页面都运行在它自己的渲染进程中。每个渲染进程是独立的,它只关心它所运行的页面。
主进程与渲染器进程之间的关系
- 主进程通过创建 BrowserWindow 实例来创建网页。 每一个 BrowserWindow 实例在其渲染过程中运行网页。当一个 BrowserWindow 实例被摧毁时,对应的渲染器过程也被终止。
- 主进程管理所有网页及其对应的渲染器进程。
- 渲染器进程只能管理每个相应的网页。在一个渲染过程中崩溃不会影响其他渲染过程。
- 渲染器进程通过 IPC 与主进程通信在网页上执行 GUI 操作。由于安全考虑和资源泄漏问题,直接从渲染器过程中调用与本地 GUI 有关的 API 受到限制。
注:
- IPC:进程间通信。是指两个进程的数据之间产生交互
- GUI:图形用户界面。
如何通信
ipcMain、ipcRenderer(send、on)
异步通信
异步通信,在发送消息之后,不会阻止同一进程中程序的继续运行。下列示例渲染进程发送异步消息 ping 到主进程,然后主进程回答 pong。
示例:
渲染器进程:
const ipc = require('electron').ipcRenderer
const asyncMsgBtn = document.getElementById('async-msg')
asyncMsgBtn.addEventListener('click', function () {
ipc.send('asynchronous-message', 'ping')
})
ipc.on('asynchronous-reply', function (event, arg) {
const message = `异步消息回复: ${arg}`
document.getElementById('async-reply').innerHTML = message
})
主进程:
const ipc = require('electron').ipcMain
ipc.on('asynchronous-message', function (event, arg) {
event.sender.send('asynchronous-reply', 'pong')
})
同步消息
除了以异步方式在进程之间发送消息,我们还可以使用 ipc 模块在进程之间发送同步消息,但是此方法的同步特性意味着它在完成任务时会阻止其他操作。
示例:
渲染器进程:
const ipc = require('electron').ipcRenderer
const syncMsgBtn = document.getElementById('sync-msg')
syncMsgBtn.addEventListener('click', function () {
const reply = ipc.sendSync('synchronous-message', 'ping')
const message = `同步消息回复: ${reply}`
document.getElementById('sync-reply').innerHTML = message
})
主进程:
const ipc = require('electron').ipcMain
ipc.on('synchronous-message', function (event, arg) {
event.returnValue = 'pong'
})
npm init -y 不用输入package.json的信息了
下载
npm i electron -D
下载失败时:
- 可以使用[cnpm包管理器]npmmirror.com/
npm install -g cnpm --registry=https://registry.npmmirror.com
cnpm install electron@19.0.8
2. 更换下载路径(推荐)
# 该命令会打开npm的配置文件
npm config edit
# 在空白处添加以下三条命令
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
electron_mirror=https://cdn.npmmirror.com/binaries/electron/
registry=https://registry.npmmirror.com/
# 然后关闭该窗口,重启命令行.
# 使用yarn安装
yarn 或 yarn install
3. 切换镜像
# 切换到electron下载镜像
npm config set registry https://mirrors.huaweicloud.com/electron
# 切换会默认npm镜像
npm config set registry https://registry.npmjs.org
# 切换为淘宝镜像命令
npm config set registry https://registry.npm.taobao.org
# 查看当前使用的镜像地址命令
npm config get registry
ASAR包
打包完成后,应用程序的源代码通常会被绑定到ASAR存档中,这是一种为 Electron 应用程序而设计的简易存档格式。
通过捆绑到应用程序中,可以缓解 Windows 上加载长路径名称的问题,加速加载并隐藏你的源码, 避免粗略的检查。
简单实践
新建窗口
// main.js
const { app, BrowserWindow } = require('electron');
const createWindow = () => {
const win = new BrowserWindow({
width: 1000,
height: 800,
});
// win.loadURL('httsps://zh.javascript.info/'); // 内容为外链
win.loadFile('index.html'); // 打开本地文件
};
app.whenReady().then(createWindow);
使用ES模块化报错
命名导出'BrowserWindow'未找到。请求的模块'electron'是一个CommonJS模块,它可能不支持所有的模块。
解决方法:使用commonJS语法
控制面板安全警告处理
// main.js
// 暂时关闭安全警告
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true';
推荐在index.html页面内使用
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self';script-src 'self'"
/>
default-src 代表默认规则,'self'表示限制所有的外部资源,只 允许当前域名加载资源。
项目实战
环境搭建
安装vite
npm init vite@latest electron-qianfeng-readit
cd electron-qianfeng-readit
npm i
安装electron
cnpm install electron -D
入口文件配置
// package.json
{
......
"main": "main.js",
......
}
在根目录下新建main.js
// main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
// 1
const { default: WinState } = require('electron-win-state')
const createWindow = () => {
// 1
const winState = new WinState({
defaultWidth:1000,
defaultHeight: 800
})
// 1
const win = new BrowserWindow({
// 自定义窗口状态
...winState.winOptions,
webPreferences: {
// 定义预加载js
preload:path.resolve(__dirname,'./preload/index.js')
},
// 2
show: false
})
win.loadURL('http://localhost:3000')
win.webContents.openDevTools()
// 1
winState.manage(win)
// 2
win.on('ready-to-show', ()=>{
win.show()
})
}
app.whenReady().then(() => {
createWindow()
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
注:
[1] 桌面屏幕可拖动缩放,需先安装cnpm i electron-win-state -D
[2] 等页面内容加载完后,再显示界面
运行配置
安装nodemon
cnpm i nodemon -D
配置pageage.json
{
......
"scripts": {
"start": "nodemon --exec electron . --watch ./ --ext .js,.html,.css,.vue"
},
......
}
因为上文main.js中设置loadURL为'http://localhost:3000', 即在vite.config.js设置如下:
export default defineConfig({
server: {
host: true,
port:3000,
}
})
运行npm run dev 和 npm run start
打包
安装electron-builder
cnpm i electron-builder -D
修改package.json配置
{
"scripts": {
"electron:build": "vite build & electron-builder"
},
"build": {
"files": [
"./main.js",
"./dist"
],
"directories": {
"output": "dists"
}
},
}
修改主进程main.js
const winURL = process.env.NODE_ENV === 'development' ? `http://localhost:8080` : path.resolve(__dirname, './dist/index.html');
win.loadURL(winURL);
注: 使用cnpm安装依赖,打包后的文件极大。可先删除node_modules,再使用npm或yarn进行安装。
打包时,builder需要会从github上下载文件
- 使用VPN(下载靠运气,十几分钟没进展的话,关了程序重下)
- 使用
npm config set electron_mirror=https://registry.npmmirror.com/-/binary/electron/,现在好像npm不再允许在npm config设置自定义值。可采用yarn config set electron_mirror=https://registry.npmmirror.com/-/binary/electron/,注意:不要在一个项目中用不同的包管理器!!! - 手动将文件下载到本地(下载与electron版本对应的以下四个文件)
下载地址:github.com/electron/el…
- electron-v22.0.0-win32-x64.zip
新建两个文件夹nsis和winCodeSign

- winCodeSign/winCodeSign-2.6.0 (下载winCodeSign-2.6.0.7z 再解压)
- nsis/nsis-3.0.4.1 (下载nsis-3.0.4.1.7z 再解压)
- nsis/nsis-resources-3.4.1 (下载nsis-resources-3.4.1.7z 再解压)