Electron是一个基于Chromium和Node.js,可以使用HTML、CSS和JavaScript构建跨平台应用的技术框架,兼容Mac、Windows和 Linux。虽然B/S是目前开发的主流,但是C/S仍然有很大的市场需求。受限于浏览器的沙盒限制,网页应用无法满足某些场景下的使用需求,而桌面应用可以方便地读写本地文件、发起跨域请求、调用更多系统资源,再加上Web开发低成本、高效率的优势,这种方式越来越受到开发者的喜爱。
2023年10月,我发布了《2023金秋版:基于electron-vite构建React桌面客户端》。当时的electron-vite还是1.x版本,如今已经发布了4.x版本,适配了Vite7,开发体验也更加完善。在省去了手动融合Electron和Vite繁琐过程的同时,还实现了V8字节码、主进程和预加载脚本热更新等非常实用的功能,要比自己从头搭建容易得多。
相比本系列教程的2023金秋版,本教程2025盛夏版将采用全新的Demo案例,通过开发一个批量图片压缩的实用小工具,全面掌握桌面客户端开发所涉及的各个知识点,新增了集成Chrome插件、检查更新、优化控制台输出、macOS签名等多个细节内容。
经过本教程的学习,你将掌握更全面的Electron实战开发技能。希望能够帮助各位省去摸索的时间,少走弯路,快速完成实际工作中的项目开发。React技术栈的小伙伴不要错过哟!
本教程也同步推出《2025金秋版:基于electron37+vite7的Vue桌面客户端保姆教程》
,欢迎Vue技术栈的小伙伴来阅读。
先睹为快
先看下目录了解本教程都有哪些内容。
章节目录
css
1 Electron核心概念
• 1.1 主进程(main)
• 1.2 渲染进程(renderer)
• 1.3 预加载脚本(preload)
2 初始化项目
• 2.1 配置npm国内镜像源
• 2.2 使用electron-vite新建项目
• 2.3 精简项目
• 2.4 去掉renderer的src目录
• 2.5 ESLint相关配置(选读)
• 2.6 设置DevTools快捷键
3 Vite基础配置
• 3.1 支持Sass/Scss/Less/Stylus
• 3.2 设置路径别名
4 项目架构搭建
• 4.1 项目目录结构设计
• 4.2 关于样式命名规范
• 4.3 设置全局公用样式
5 引入Ant Design 5.x
• 5.1 安装Ant Design
• 5.2 设置Antd为中文语言
• 5.3 兼容React19
6 渲染进程页面开发
• 6.1 构建Login页面
• 6.2 构建Home页面
• 6.3 允许Electron跨域请求和加载本地资源
• 6.4 构建公共Header组件
• 6.5 构建页面路由
• 6.6 构建框架页面Entry
• 6.7 引入路由
• 6.8 路由跳转:Login页面跳转Home页面
• 6.9 路由守卫
• 6.10 路由跳转:退出返回登录页
7 主进程与渲染进程通信方式一:暴露electronAPI给渲染进程
• 7.1 预加载脚本(preload)
• 7.2 构建"关于软件"弹窗
8 主进程与渲染进程通信方式二:send与on/once
• 8.1 预加载脚本(preload)开发
• 8.2 主进程开发:读取目录中的全部图片文件
• 8.3 继续渲染进程Home页面开发
• 8.4 运行效果
• 8.5 解决windows系统主进程控制台中文乱码的问题
• 8.6 实现系统控制台多彩文字色输出
• 8.7 实现设置输出目录
• 8.8 关于ipcRenderer.on/once
9 主进程与渲染进程通信方式三:invoke与handle
• 9.1 实现主进程图片压缩处理
• 9.2 使用invoke与handle串通渲染进程与主进程
• 9.3 为什么不使用send与on/once
10 其他Electron常用配置
• 10.1 设置应用图标
• 10.2 设置APP窗口大小
• 10.3 禁止生产环境的DevTools
• 10.4 集成Chrome插件
• 10.5 禁止启动同个Electron应用
11 build项目
• 11.1 Electron相关镜像源配置(无需更改)
• 11.2 设置build版应用icon
• 11.3 配置macOS的签名
• 11.3.1 无签名版应用(可安装,但不能自动更新)
• 11.3.2 有签名版应用(可安装,可自动更新)
• 11.4 设置不需要打包的目录
• 11.5 执行build命令
• 11.6 build后的目录结构
• 11.7 设置windows安装包允许用户自定义安装目录
• 11.8 设置windows安装包强制安装路径(选读)
• 11.8.1 全局安装(C:\Program Files)
• 11.8.2 指定默认目录安装
12 自动更新
• 12.1 部署更新服务器
• 12.2 实现主进程检查更新的逻辑
• 12.3 设置更新服务器地址的几种方式
• 12.3.1 主进程 autoUpdater.setFeedURL(推荐)
• 12.3.2 electron-builder.yml(不使用)
• 12.3.3 dev-app-update.yml(不使用)
• 12.4 在渲染进程实现静默检查更新和自动下载
• 12.5 在渲染进程实现手动检查更新和手动下载
13 其他说明
• 13.1 源代码保护
• 13.2 敏感字符串保护
• 13.3 主进程热更新(选读)
• 13.4 批量升级全部项目npm依赖包
• 13.5 项目的不足之处
14 项目Git源码
结束语
主要依赖包版本
本教程的主要依赖包版本:
bash
Node.js 22.17.1
electron 37.2.3
electron-builder 26.0.12
electron-vite 4.0.0
electron-updater 6.6.2
eslint 9.31.0
react 19.1.0
react-dom 19.1.0
react-router-dom 7.7.0
vite 7.0.5
antd 5.26.6
sharp 0.34.3
@ant-design/v5-patch-for-react-19 1.0.3
※注:
代码区域每行开头的:
"+" 表示新增
"-" 表示删除
"M" 表示修改
跟着教程操作一遍,就可以快速上手Electron开发啦!下面请跟着新版教程一步步操作。
最终成品预览


1 Electron核心概念
学习Electron最先要掌握的就是它的主进程与渲染进程概念。网上很多相关教程也进行了详细介绍,又是画关系图又是文字描述的。这里只想把最核心的内容总结一下,以最简单最通俗的方式让各位迅速理解。
掌握三个核心概念即可:
1.1 主进程(main)
每个Electron应用都有一个单一的主进程,作为应用程序的入口点。主进程运行在Node.js环境,因此可以使用Node.js的所有API能力。主进程并不在浏览器环境中运行,因此不进行页面渲染。
1.2 渲染进程(renderer)
渲染进程说白了就是平时的Web页面前端开发。每个Electron应用都会为每个打开的BrowserWindow生成一个单独的渲染器进程。但是渲染进程是无法直接调用Node.js的API的。
1.3 预加载脚本(preload)
为了让渲染进程与主进程进行通信从而形成一个整体,预加载脚本的作用就是它们之间的桥梁。预加载脚本属于渲染进程的范畴,与渲染进程共享同一个全局window,因此可以通过window来传递数据。但并不是简单地通过给window添加属性就能使用,以下方式是无法把preload.js共享给渲染进程使用的:
javascript
// 预加载脚本(preload.js)
window.myAPI = {
desktop: true
}
// 渲染进程
console.log(window.myAPI)
// => undefined(获取不到)
这是因为Electron的语境隔离(Context Isolation),使得预加载脚本与渲染进程的主要运行环境是隔离的,以避免将任何API都加入到渲染进程的网页中。
因此,需要使用contextBridge来安全地实现交互:
javascript
// 预加载脚本(preload.js)
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
desktop: true
})
// 渲染进程
console.log(window.myAPI)
// => { desktop: true } (成功获取)
以上方式就是通过contextBridge.exposeInMainWorld
将preload.js中的myAPI数据共享给渲染进程的网页使用。
官网详细介绍:
2 初始化项目
2.1 配置npm国内镜像源
npm默认是从国外源站拉取依赖包的,为提高下载速度和稳定性,建议配置为国内镜像源。
执行:
arduino
npm config set registry https://registry.npmmirror.com
执行后,可以通过以下命令查看npm配置,确认是否设置成功:
arduino
npm config list
输出的内容中,检查registry的值是否已改为国内镜像源地址:
ini
registry = "https://registry.npmmirror.com/"
2.2 使用electron-vite新建项目
找个合适的目录,执行项目创建命令:
sql
npm create @quick-start/electron@latest
执行后,会要求填写项目名称,这里我填写的是electron-vite-react-app,可根据情况自定。
yaml
? Project name: electron-vite-react-app
然后,会要求选择框架,选择react:
css
? Select a framework:
vanilla
vue
> react
svelte
solid
最后是几个配置选项:
yaml
? Add TypeScript? >> No
是否使用TypeScript?选No,本教程使用JavaScript。如果喜欢TypeScript,请选择Yes。
? Add Electron updater plugin? >> Yes
是否添加Electron updater插件?选择Yes。
? Enable Electron download mirror proxy? >> Yes
是否开启Electron镜像下载代理。在国内网络环境,强烈建议选择Yes。
项目创建完成后,执行以下命令:
bash
cd electron-vite-react-app
npm install
安装完成后,执行启动命令:
arduino
npm run dev
运行效果如下:

2.3 精简项目
接下来,删除用不到的目录和文件,最简化项目。
bash
├─ /.vscode
├─ /build
├─ /node_modules
├─ /out
├─ /resources
├─ /src
| ├─ /main
| ├─ /preload
| ├─ /renderer
| | ├─ /src
- | | | ├─ /assets
| | | ├─ /components
- | | | | └─ Versions.jsx
| | | ├─ App.jsx
| | | └─ main.jsx
| | └─ index.html
├─ .editorconfig
├─ .gitignore
├─ .npmrc
├─ .prettierignore
├─ .prettierrc.yaml
├─ dev-app-update.yml
├─ electron-builder.yml
├─ electron.vite.config.js
├─ eslint.config.mjs
├─ package-lock.json
├─ package.json
└─ README.md
2.4 去掉renderer的src目录
以上项目结构有两个src目录,容易混淆,而且路径表达也略显啰嗦。可以把 src/renderer/src
目录里的文件放到 src/renderer
目录中,然后删除 src/renderer/src
目录。
调整后的renderer目录如下:
bash
...(略)
| ├─ /renderer
| | ├─ /components
| | ├─ App.jsx
| | ├─ index.html
| | └─ main.jsx
...(略)
以上文件删除后,页面会报错。这是因为相应的文件引用已不存在。需要继续修改代码,先让项目正常运行起来。
逐个修改以下文件,最终精简代码依次如下:
src/renderer/App.jsx
:
javascript
function App() {
return <div className="App">Electron-Vite-React-App</div>
}
export default App
src/renderer/main.jsx
:
javascript
import ReactDOM from 'react-dom/client'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')).render(<App />)
src/renderer/index.html
:
xml
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>图片压缩小工具</title>
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:"
/>
</head>
<body>
<div id="root"></div>
<script type="module" src="./main.jsx"></script>
</body>
</html>
在windows环境中,src/renderer/index.html
的<title>
内容将显示在客户端窗口标题栏中。
执行:
arduino
npm run dev
运行效果如下:

2.5 ESLint相关配置(选读)
在 src/renderer/App.jsx
文件中,VSCode会提示如下:

这是因为在一个项目中同时使用ESLint和Prettier时,两者对代码格式有不同的规则从而导致冲突。
有代码洁癖的话,这就不能忍。需要解决它。
最简单的办法就是关闭掉ESlint对Prettier格式的检测。
修改 eslint.config.mjs
:
javascript
import eslint from '@electron-toolkit/eslint-config'
M // import eslintConfigPrettier from '@electron-toolkit/eslint-config-prettier'
import eslintPluginReact from 'eslint-plugin-react'
import eslintPluginReactHooks from 'eslint-plugin-react-hooks'
import eslintPluginReactRefresh from 'eslint-plugin-react-refresh'
export default [
...(略)
M // eslintConfigPrettier
]
注释掉eslintConfigPrettier即可。
另外,也分享一下我的ESLint完整配置,添加了对React的一些代码格式规范,供参考:
javascript
import eslint from '@electron-toolkit/eslint-config'
// import eslintConfigPrettier from '@electron-toolkit/eslint-config-prettier'
import eslintPluginReact from 'eslint-plugin-react'
import eslintPluginReactHooks from 'eslint-plugin-react-hooks'
import eslintPluginReactRefresh from 'eslint-plugin-react-refresh'
export default [
{ ignores: ['**/node_modules', '**/dist', '**/out'] },
eslint,
eslintPluginReact.configs.flat.recommended,
eslintPluginReact.configs.flat['jsx-runtime'],
{
settings: {
react: {
version: 'detect'
}
}
},
{
files: ['**/*.{js,jsx}'],
plugins: {
'react-hooks': eslintPluginReactHooks,
'react-refresh': eslintPluginReactRefresh
},
rules: {
...eslintPluginReactHooks.configs.recommended.rules,
...eslintPluginReactRefresh.configs.vite.rules,
+ // 设置未使用变量的检查规则
+ 'no-unused-vars': ['warn', { vars: 'all', args: 'none', ignoreRestSiblings: false }],
+ // 取消对react prop传参的检查
+ 'react/prop-types': 'off',
+ // 取消对自定义HTML属性的检查 react/no-unknown-property
+ 'react/no-unknown-property': 'off',
+ // 降级对target="_blank" without rel="noreferrer"的警告
+ 'react/jsx-no-target-blank': 'warn'
}
}
// eslintConfigPrettier
]
.prettierrc.yaml
是prettier的配置文件,供参考:
yaml
# JavaScript中的代码使用单引号(')代替双引号(")
singleQuote: true
# 每行代码末尾不加分号
semi: false
# 每行代码最大长度100个字符,超出时 Prettier 会自动换行
printWidth: 100
# 对象、数组、函数参数列表等结构中,最后一项不加逗号。
trailingComma: none
# 缩进时使用 4 个空格
tabWidth: 4
# 使用空格进行缩进,而不是 Tab 字符。确保不同编辑器显示一致。
useTabs: false
# 自动检测操作系统使用的换行符(Linux 是 \n,Windows 是 \r\n)。适用于跨平台开发,避免换行符冲突。
endOfLine: auto
经过以上设置,就可以治愈代码洁癖强迫症了。
2.6 设置DevTools快捷键
Chrome的调试工具在是开发中必不可少的利器。默认情况下,Electron是没有鼠标右键的。打开DevTools的默认方式为:
windows快捷键:Shift+Ctrl+I
(英文字母"艾")
macOS快捷键:Command+Option+I
(英文字母"艾")
也可以自定义设置快捷键。
修改 src/main/index.js
:
javascript
- import { app, shell, BrowserWindow, ipcMain } from 'electron'
+ import { app, shell, BrowserWindow, ipcMain, globalShortcut } from 'electron'
...(略)
function createWindow() {
...(略)
// HMR for renderer base on electron-vite cli.
// Load the remote URL for development or the local html file for production.
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
} else {
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
}
+ // 设置DevTools快捷键
+ globalShortcut.register('CommandOrControl+Shift+i', function () {
+ mainWindow.webContents.openDevTools()
+ })
}
...(略)
经过以上设置,DevTools打开方法为:
windows快捷键:Ctrl+Shift+I
(与默认一致)
macOS快捷键:Command+Shift+I
(默认的Option换成了Shift)
当然,之前默认的DevTools打开快捷键仍然生效。

3 Vite基础配置
3.1 支持Sass/Scss/Less/Stylus
Vite本身提供了对.scss/.sass/.less/.styl/.stylus文件的内置支持。无需再安装特定的Vite插件,但必须安装相应的预处理器依赖。
支持Sass/Scss,执行以下命令:
npm install -D sass
支持Less,执行以下命令:
npm install -D less
支持Stylus,执行以下命令:
npm install -D stylus
安装后,就可以直接使用以上对应的CSS预处理语言了,非常方便。
CSS预处理Vite官方说明:
3.2 设置路径别名
electron-vite已经预设了路径别名配置。
例如:src/renderer/App.jsx
,可以直接省略成 @renderer/App.jsx
。
由于本教程已经删除了src/renderer/src
目录,因此需要修改对应的预设配置。
修改 electron.vite.config.mjs
:
css
...(略)
renderer: {
resolve: {
alias: {
- '@renderer': resolve('src/renderer/src')
+ '@renderer': resolve('src/renderer')
}
},
plugins: [react()]
}
...(略)
4 项目架构搭建
4.1 项目目录结构设计
项目目录结构可根据项目实际灵活制定。这里分享下我常用的结构。重点是renderer目录的结构设计,主要分为公用模块目录、组件模块目录、页面模块目录、路由配置目录等几个部分,让项目结构更加清晰合理。
❤️❤️❤️------试读结束------❤️❤️❤️
后续精彩章节
bash
• 4.1 项目目录结构设计
• 4.2 关于样式命名规范
• 4.3 设置全局公用样式
5 引入Ant Design 5.x
• 5.1 安装Ant Design
• 5.2 设置Antd为中文语言
• 5.3 兼容React19
6 渲染进程页面开发
• 6.1 构建Login页面
• 6.2 构建Home页面
• 6.3 允许Electron跨域请求和加载本地资源
• 6.4 构建公共Header组件
• 6.5 构建页面路由
• 6.6 构建框架页面Entry
• 6.7 引入路由
• 6.8 路由跳转:Login页面跳转Home页面
• 6.9 路由守卫
• 6.10 路由跳转:退出返回登录页
7 主进程与渲染进程通信方式一:暴露electronAPI给渲染进程
• 7.1 预加载脚本(preload)
• 7.2 构建"关于软件"弹窗
8 主进程与渲染进程通信方式二:send与on/once
• 8.1 预加载脚本(preload)开发
• 8.2 主进程开发:读取目录中的全部图片文件
• 8.3 继续渲染进程Home页面开发
• 8.4 运行效果
• 8.5 解决windows系统主进程控制台中文乱码的问题
• 8.6 实现系统控制台多彩文字色输出
• 8.7 实现设置输出目录
• 8.8 关于ipcRenderer.on/once
9 主进程与渲染进程通信方式三:invoke与handle
• 9.1 实现主进程图片压缩处理
• 9.2 使用invoke与handle串通渲染进程与主进程
• 9.3 为什么不使用send与on/once
10 其他Electron常用配置
• 10.1 设置应用图标
• 10.2 设置APP窗口大小
• 10.3 禁止生产环境的DevTools
• 10.4 集成Chrome插件
• 10.5 禁止启动同个Electron应用
11 build项目
• 11.1 Electron相关镜像源配置(无需更改)
• 11.2 设置build版应用icon
• 11.3 配置macOS的签名
• 11.3.1 无签名版应用(可安装,但不能自动更新)
• 11.3.2 有签名版应用(可安装,可自动更新)
• 11.4 设置不需要打包的目录
• 11.5 执行build命令
• 11.6 build后的目录结构
• 11.7 设置windows安装包允许用户自定义安装目录
• 11.8 设置windows安装包强制安装路径(选读)
• 11.8.1 全局安装(C:\Program Files)
• 11.8.2 指定默认目录安装
12 自动更新
• 12.1 部署更新服务器
• 12.2 实现主进程检查更新的逻辑
• 12.3 设置更新服务器地址的几种方式
• 12.3.1 主进程 autoUpdater.setFeedURL(推荐)
• 12.3.2 electron-builder.yml(不使用)
• 12.3.3 dev-app-update.yml(不使用)
• 12.4 在渲染进程实现静默检查更新和自动下载
• 12.5 在渲染进程实现手动检查更新和手动下载
13 其他说明
• 13.1 源代码保护
• 13.2 敏感字符串保护
• 13.3 主进程热更新(选读)
• 13.4 批量升级全部项目npm依赖包
• 13.5 项目的不足之处
14 项目Git源码
结束语
阅读完整版
📖 完整教程可订阅我的公众号【卧梅又闻花
】
《2025盛夏版:基于electron37+vite7的React桌面客户端保姆教程(上篇)》
《2025盛夏版:基于electron37+vite7的React桌面客户端保姆教程(下篇)》
项目Git源码
本项目已上传至Gitee和GitHub,方便各位下载。
Gitee:
gitee.com/betaq/elect...
Github: