跳到主要内容
Electron 一小时快速上手:前端桌面应用开发教程 | 极客日志
JavaScript Node.js 大前端
Electron 一小时快速上手:前端桌面应用开发教程 综述由AI生成 介绍 Electron 框架的基础概念及快速上手流程。涵盖工程初始化、主进程与渲染进程通信机制、本地文件读写操作以及使用 Electron Forge 进行跨平台打包的方法。通过实际案例演示了如何构建兼容 Windows、Linux 和 macOS 的桌面应用程序,并解决了内容安全策略(CSP)及热更新配置等常见问题。
追风少年 发布于 2026/4/6 更新于 2026/5/16 26 浏览
注意 :
原视频打包时使用 electron-builder,访问 GitHub 可能需要特殊网络环境。
本笔记使用 Electron Forge 进行打包,无需访问 GitHub,更友好。Electron 官网也推荐使用这种方式。
一、Electron 是什么
简单的一句话,就是用 HTML+CSS+JS+Node.js+(Native API) 做兼容多个系统(Windows、Linux、Mac)的软件。
官网解释如下:
Electron 是一个使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。嵌入 Chromium 和 Node.js 到二进制的 Electron 允许您保持一个 JavaScript 代码库并创建在 Windows 上运行的跨平台应用 macOS 和 Linux——不需要本地开发经验。
二、Electron 流程模型
三、Electron 搭建工程,若成功则输出 123
3.1 准备
需要 node 和 npm,先检测是否安装。
node -v
npm -v
3.2 项目初始化
命令行创建:
mkdir my-electron-app && cd my-electron-app
npm init
或者手动快速创建。
package.json 文件示例:
{
"name" : "my-electron-app"
,
"version"
:
"1.0.0"
,
"description"
:
"test Electron"
,
"main"
:
"main.js"
,
"author"
:
"Author Name"
,
"license"
:
"MIT"
}
entry point 应为 main.js。
author 与 description 可为任意值,但对于应用打包是必填项。
3.3 安装 Electron npm install --save-dev electron
// 或者
npm install electron -D
3.4 配置并启动 在 package.json 配置文件中的 scripts 字段下增加一条 start 命令:
{
"scripts" : {
"start" : "electron ."
}
}
{
"name" : "my-electron-app" ,
"version" : "1.0.0" ,
"main" : "main.js" ,
"scripts" : {
"start" : "electron ."
} ,
"author" : "bin9153" ,
"license" : "ISC" ,
"description" : "electron test" ,
"dependencies" : {
"electron" : "^31.2.0"
}
}
先创建 main.js,否则报错。
如果 main.js 里没写输出(或其他代码)则,启动了运行窗口也不容易看出变化。
四、开始制作程序
4.1 案例 1:做一个简易网页程序 const { app, BrowserWindow } = require ('electron' )
app.on ('ready' , () => {
const win = new BrowserWindow ({
width : 800 ,
height : 600 ,
autoHideMenuBar : true ,
alwaysOnTop : true ,
x : 0 ,
y : 0
})
win.loadURL ('https://example.com' )
})
4.2 案例 2:做一个本地程序(不是远程链接页面,是自己写的页面)
4.2.1 是本地程序,所以创建新的页面 新建 pages 目录,创建页面,这里就像写前端一样了。index.html, index.css。
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<title > 这里是 index 页面</title >
</head >
<body >
<h1 > 这里是 index 里的标题</h1 >
</body >
</html >
const { app, BrowserWindow } = require ('electron' )
app.on ('ready' , () => {
const win = new BrowserWindow ({
width : 800 ,
height : 600 ,
autoHideMenuBar : true ,
alwaysOnTop : true
})
win.loadFile ('./pages/index/index.html' )
})
4.2.2 解决内容安全策略 在 index.html 里加入如下代码,内容安全策略警告提示消失。
<meta http-equiv ="Content-Security-Policy" content ="default-src 'self'; script-src 'self'" >
<meta http-equiv ="Content-Security-Policy" content ="default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src self 'data:';" >
4.2.3 增加多系统的兼容代码 在 main.js 里写入兼容各个系统平台的代码:
const { app, BrowserWindow } = require ('electron' )
function createWindow ( ) {
const win = new BrowserWindow ({
width : 800 ,
height : 600 ,
autoHideMenuBar : true ,
alwaysOnTop : true
})
win.loadFile ('./pages/index/index.html' )
}
app.on ('ready' , () => {
createWindow ()
app.on ('activate' , () => {
if (BrowserWindow .getAllWindows ().length === 0 ) createWindow ()
})
})
app.on ('window-all-closed' , () => {
if (process.platform !== 'darwin' ) app.quit ()
})
app.on ('ready' , () => { })
app.whenReady ().then (() => { })
4.2.4 配置自动重启,保存后自动热更新 "start" : "nodemon --exec electron ."
这样保存 main.js 里的内容,就自动热更新了。
但是更新 index.html 里的代码不能热更新,要加一个 nodemon.json,需要手动添加:
{
"ignore" : [ "node_modules" , "dist" ] ,
"restartable" : "r" ,
"watch" : [ "*.*" ] ,
"ext" : "html,js,css"
}
4.2.5 编写页面程序 (写一个应用程序,可以写入任意文字到 hello.txt 里) 每个页面程序通过渲染和主进程通信,主进程根据需求调用 Native API 来实现功能。
实际,每个页面和主程序通信时,需要建个桥梁来管理它们的通信,preload.js(自己创建),来管理实现通信。
在 main.js 中定义 preload.js 为桥梁
const { app, BrowserWindow } = require ('electron' )
const path = require ('path' )
function createWindow ( ) {
const win = new BrowserWindow ({
width : 800 ,
height : 600 ,
autoHideMenuBar : true ,
alwaysOnTop : true ,
webPreferences : {
preload : path.resolve (__dirname, './preload.js' )
}
})
win.loadFile ('./pages/index/index.html' )
win.openDevTools ()
console .log ("main.js" )
}
app.on ('ready' , () => {
createWindow ()
app.on ('activate' , () => {
if (BrowserWindow .getAllWindows ().length === 0 ) createWindow ()
})
})
这是自己整理的,整理了前面 45 分钟,再这么整理下去,1000 字也不够用。
直接上代码。
const { app, BrowserWindow , ipcMain } = require ('electron' )
const path = require ('path' )
const fs = require ('fs' )
function writeFile (_, data ) {
fs.writeFileSync ('D:/hello.txt' , data)
}
function readFile ( ) {
const res = fs.readFileSync ("D:/hello.txt" ).toString ()
return res
}
function createWindow ( ) {
const win = new BrowserWindow ({
width : 800 ,
height : 600 ,
autoHideMenuBar : true ,
alwaysOnTop : true ,
webPreferences : {
preload : path.resolve (__dirname, './preload.js' )
}
})
ipcMain.on ('file-save' , writeFile)
ipcMain.handle ('file-read' , readFile)
win.loadFile ('./pages/index/index.html' )
win.openDevTools ()
console .log ("main.js" )
}
app.on ('ready' , () => {
createWindow ()
app.on ('activate' , () => {
if (BrowserWindow .getAllWindows ().length === 0 ) createWindow ()
})
})
const { contextBridge, ipcRenderer } = require ('electron' )
contextBridge.exposeInMainWorld ('myAPI' , {
version : process.version ,
saveFile : (data ) => {
ipcRenderer.send ('file-save' , data)
},
readFile ( ) {
return ipcRenderer.invoke ('file-read' )
}
})
const btn1 = document .getElementById ("btn1" )
const btn2 = document .getElementById ("btn2" )
const btn3 = document .getElementById ("btn3" )
const input = document .getElementById ("inp" )
btn1.onclick = () => {
alert (myAPI.version )
}
btn2.onclick = () => {
myAPI.saveFile (input.value )
}
btn3.onclick = async () => {
const res = await myAPI.readFile ()
alert (res)
}
<!DOCTYPE html >
<html lang ="en" >
<head >
<meta charset ="UTF-8" >
<meta http-equiv ="Content-Security-Policy" content ="default-src 'self'; script-src 'self'" >
<title > 这里是 index 页面</title >
</head >
<body >
<h1 > 欢迎学习 Electron 开发!!!</h1 >
<button id ="btn1" > 点我</button >
<hr />
<input type ="text" id ="inp" />
<button id ="btn2" > 向 D 盘写入 hello.txt</button >
<hr >
<button id ="btn3" > 读取 hello.txt 的内容</button >
<script type ="text/javascript" src ="./render.js" > </script >
</body >
</html >
代码稍微有点不一样。
目录结构也有变化,功能是一样的。
五、打包
5.1 使用 electron-builder 打包 npm install electron-builder -D
在 package.json 中进行相关配置,具体配置如下:
备注:json 文件不支持注释,使用时请去掉所有注释。
{
"name" : "video-tools" ,
"version" : "1.0.0" ,
"main" : "main.js" ,
"scripts" : {
"start" : "electron ." ,
"build" : "electron-builder"
} ,
"build" : {
"appId" : "com.atguigu.video" ,
"win" : {
"icon" : "./logo.ico" ,
"target" : [ { "target" : "nsis" , "arch" : [ "x64" ] } ]
} ,
"nsis" : {
"oneClick" : false ,
"perMachine" : true ,
"allowToChangeInstallationDirectory" : true
}
} ,
"devDependencies" : {
"electron" : "^30.0.0" ,
"electron-builder" : "^24.13.3"
} ,
"author" : "Author" ,
"license" : "ISC" ,
"description" : "A video processing program based on Electron"
}
根据视频操作未能完成打包,这种方式在打包时访问 GitHub 多次尝试后,决定放弃。
5.2 使用 Electron Forge 进行打包
5.2.1 使用 3 条命令,完成打包。 npm install --save-dev @electron-forge/cli
npx electron-forge import
这时在 package.json 里会增加一些配置。
5.2.2 打包后的位置,在根项目下的 out 文件里
可运行程序在 my-electron-app\out\make\squirrel.windows\x64
5.2.3 看运行效果,终于完成了。
5.2.4 出现的 bug
安装一次后再打开会报错。
直接删除软件,目录在 C:\Users\Administrator\AppData\Roaming 删除 my_electron_app 这个文件夹。然后用 360 安全卫士清理垃圾。然后重启即可。
其他 bug
软件有卡死的现象。
还会自动重启。
软件关闭后会自动重启。
在输入框中输入内容,写入后可能会卡死,第二次可能无法输入,但可以读取。
启动时有点卡。
六、总结
后面有的 bug 可能与 Electron Forge 配置有关。有时间试试,找个解决方案。
也有可能与 main.js 写法有关。
打包时删除 main.js 里的 win.openDevTools(),否则软件会自动打开调试窗口。
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online