Electron从构建到打包程exe应用
Electron从构建到打包程exe应用
- Electron文档
- 搭建
- 网页装载到 BrowserWindow中
- 定义全局对象
- 进程之间通信
- 渲染器进程到主进程(单向)
- 渲染器进程到主进程(双向)
- 主进程到渲染器进程
- 打开调试器
- 打包应用程序
- 对代码进行签名
Electron文档
搭建
创建一个文件夹,在根目录执行以下几个命令
1.npm init
2.npm install electron --save-dev
3.根目录新增main.js文件,添加内容console.log("hellow!!")
4.package.json中更改"main": "main.js","scripts":{"start": "electron .", }
然后运行根目录执行命令npm run start
可以在命令行中看到hellow!!,此时项目算是跑通了

网页装载到 BrowserWindow中
1.根目录新增index.html文件,写添加html的默认代码等标签,并添加一个hellow
<!DOCTYPE html>
<body><h1>Hello!!</h1>
</body>
2.根目录新增main.js
const { app, BrowserWindow } = require('electron');//导入Electron模块// 函数index.html页面加载到新的 BrowserWindow 实例中
const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600});//设置BrowserWindow 窗口的宽高win.loadFile('index.html');
}// 应用准备就绪时调用函数
app.whenReady().then(() => {createWindow()})
// app.on('ready', () => {createWindow()}) 不建议这么调用// 退出应用程序,不兼容macOS
app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit()}
})
运行npm start ,会打开一个浏览器窗口

定义全局对象
1.根目录新加新建一个 preload.js,并添加如下代码
const { contextBridge } = require('electron')// 设置全局变量versions
contextBridge.exposeInMainWorld('versions', {// 使用功函数的形式,node: () => process.versions.node, // 调用:versions.node()chrome: () => process.versions.chrome,electron: () => process.versions.electron// 除函数之外,我们也可以暴露变量isBool:true
})
2.将preload.js的代码渲染到进程上,main.js文件中添加如下代码
const path = require('path')// new BrowserWindow中添加如下代码
webPreferences: {preload: path.join(__dirname, 'preload.js')
}
3.根目录新加新建一个 renderer.js,并添加如下代码
const el= document.getElementById('info')
// 调用versions下的方法
el.innerText = ` Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), 和 Electron (v${versions.electron()})`
console.log(versions.isBool) // true
/*
注意: Electron 12 以来,默认情况下已启用上下文隔离,
所以在preload.js中设置window.myAPI全局变量的话,在 renderer.js里面window.myAPI为undefined
window.myAPI = {desktop: true
}
*/
4.将renderer.js引入到index.html,并添加一个id为info的标签
<div id="info"></div>
<script src="./renderer.js"></script>
运行 npm start

进程之间通信
使用 Electron 的 ipcMain 模块和 ipcRenderer 模块来进行进程间通信
渲染器进程到主进程(单向)
将单向 IPC 消息从渲染器进程发送到主进程,使用 ipcRenderer.send API 发送消息,然后使用 ipcMain.on API 接收。
1.main.js添加如下代码
app.whenReady().then(() => {...// 使用ipcMain.on侦听事件监听set-titleipcMain.on('set-title', (event, title) => {const webContents = event.senderconst w = BrowserWindow.fromWebContents(webContents)w.setTitle(title)});})
2.preload.js添加如下代码
// 将消息发送到上面的ipcMain.on监听器,使用 ipcRenderer.send API
contextBridge.exposeInMainWorld('versions', {...setTitle: (title) => ipcRenderer.send('set-title',title),
})
3.触发(调用)versions.setTitle,
// index.html里面新增代码
<input id="btn" type="button" value="渲染器进程到主进程(单向)-设置标题"/>// renderer.js里面新增代码
const buttonel = document.getElementById('btn')
buttonel.addEventListener('click', () => {const title = buttonel.valueversions.setTitle(title)
})
运行npm run start

渲染器进程到主进程(双向)
双向 IPC 的一个常见应用是从渲染器进程代码调用主进程模块并等待结果。
通过将 ipcRenderer.invoke 与 ipcMain.handle 搭配使用来完成
步骤:
1.网页向主进程发送消息,使用 ipcMain.handle 设置一个主进程处理程序
2.然后在预处理脚本中暴露一个 ipcRenderer.invoke 的函数来触发该处理程序
演示代码如下
1.在main.js中添加如下代码
const { ipcMain } = require('electron')
app.whenReady().then(() => {// 设置一个主进程处理程序发送器,监听myfn12ipcMain.handle('myfn12', (event,arg) => {return '我是myfn的返回:'+ arg;});...
})
2.preload.js添加如下代码
contextBridge.exposeInMainWorld('versions', {...,electron: () => process.versions.electron,myfn: (arg) => ipcRenderer.invoke('myfn12',arg)
})
3.renderer.js新增里面添加如下代码
const fn = async () => {const response = await versions.myfn('我传一个参数个myfn');// 传参,接收返回的参数information.innerHTML = `${response}`
}
fn()
运行npm start如下图

主进程到渲染器进程
将消息从主进程发送到渲染器进程时,需要指定是哪一个渲染器接收消息。 消息需要通过其 WebContents 实例发送到渲染器进程。 此 WebContents 实例包含一个 send 方法,其使用方式与 ipcRenderer.send 相同
我们实现如下功能,切换菜单触发
main.js新增如下代码
const { Menu } = require('electron')
const createWindow = () => {
const win = new BrowserWindow({...})
// ++利用Menu 模块 构建一个菜单const menu = Menu.buildFromTemplate([{label: app.name, // 主菜单使用当前应用的名字submenu: [{click: () => win.webContents.send('update-counter', 1), // 点击子菜单的事件,通过 update-counter 通道向渲染器进程发送消息1label: 'Increment' // 子菜单的名字},{click: () => win.webContents.send('update-counter', -1),// 点击子菜单的事件label: 'Decrement' // 子菜单的名字}]}])Menu.setApplicationMenu(menu)
}app.whenReady().then(() => {...// ++监听counter-valueipcMain.on('counter-value', (_event, value) => {console.log('avlue'+value) // will print value to Node console})
})
preload.js新增如下代码
contextBridge.exposeInMainWorld('versions', {...handleCounter: (callback) => ipcRenderer.on('update-counter', callback), // 再此处监听update-counter
})
renderer.js新增如下代码
const counter = document.getElementById('counter')
/*
调用handleCounter后,会开始监听"update-counter"(监听的代码在preload.js中),
点击菜单的时候会发送数据到update-counter触发,进入到下面的回调中,进入回调后,向counter-value发送了数据,
在main.js中counter-value中可以监听到数据,
*/
window.versions.handleCounter((event, value) => {const oldValue = Number(counter.innerText)const newValue = oldValue + valuecounter.innerText = newValueevent.sender.send('counter-value', newValue); // 在此处send
})
index.html新增如下代码
当前值: <strong id="counter">0</strong>
运行npm start 效果如下

打开调试器
// 打开 DevTools.win.webContents.openDevTools()
运行npm start如下,打开了谷歌的调试器

打包应用程序
将 Electron Forge 的 CLI 工具包安装到项目的 devDependencies 依赖中,然后使用现成的转化脚本将项目导入至 Electron Forge。
Electron Forge CLI 文档。
1.根目录运行以下命令,安装依赖
npm install --save-dev @electron-forge/cli
npx electron-forge import
安装完后会发现,package.json中多了一些代码,以及多了一个 forge.config.js文件

2,。运行以下命令
npm run make
如果出现以下报错,记得填写package.json中的description和author

打包完成后,根目录会出现一个 out 文件夹,其中包括可分发文件与一个包含其源码的文件夹
out/
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
├── ...
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
out/make 文件夹中的应用程序(.exe),双击exe文件就可以启动了

对代码进行签名
代码签名是交付桌面应用程序的重要组成部分,并且它对于应用程序的自动更新功能 (将会在教程最后部分讲解) 来说是必需的
为了将桌面应用程序分发给最终用户,建议应用进行代码签名。
在 macOS 上,代码签名是在应用程序打包时完成的。 而在 Windows 中,则是对可分发文件进行签名操
如果您已经拥有适用于 Windows 和 macOS 的代码签名证书,可以在 Forge 配置中设置您的凭据
签署 macOS 应用程序 指南
macOS端
forge.config.js文件
module.exports = {packagerConfig: {osxSign: {},// ...osxNotarize: {tool: 'notarytool',appleId: process.env.APPLE_ID,appleIdPassword: process.env.APPLE_PASSWORD,teamId: process.env.APPLE_TEAM_ID}// ...}
}
Windows端
forge.config.js文件
module.exports = {// ...makers: [{name: '@electron-forge/maker-squirrel',config: {certificateFile: './cert.pfx',certificatePassword: process.env.CERTIFICATE_PASSWORD}}]// ...
}
相关文章:
Electron从构建到打包程exe应用
Electron从构建到打包程exe应用 Electron文档搭建网页装载到 BrowserWindow中定义全局对象进程之间通信渲染器进程到主进程(单向)渲染器进程到主进程(双向)主进程到渲染器进程 打开调试器打包应用程序对代码进行签名 Electron文档…...
3分钟学会设计模式 -- 单例模式
►单例模式 ►使用场景 在编写软件时,对于某些类来说,只有一个实例很重要。例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统中可以多次查询数据库,但是只需要一个连接&#x…...
《面试1v1》Kafka与传统消息系统区别
🍅 作者简介:王哥,CSDN2022博客总榜Top100🏆、博客专家💪 🍅 技术交流:定期更新Java硬核干货,不定期送书活动 🍅 王哥多年工作总结:Java学习路线总结…...
【算法第十三天7.27】平衡二叉树,二叉树所有路径,左叶子之和
链接力扣110-平衡二叉树 思路 1、左右子树高度差不超过1 2、左子树、右子树均为平衡二叉树 3、需要获得树高,如果不是平衡的就返回-1;如果是平衡,就返回对应的高 class Solution {public boolean isBalanced(TreeNode root) {return getH…...
arm架构cloudstack的agent报错No more available PCI slots如何解决
当ARM架构的CloudStack代理报错"No more available PCI slots"时,这通常表示ARM实例已用尽可用的PCI插槽。PCI插槽用于连接网络接口卡(NIC)和其他扩展设备到虚拟机实例。 解决此问题的方法可以考虑以下几点: 调整实例的…...
day43-Feedback Ui Design(反馈ui设计)
50 天学习 50 个项目 - HTMLCSS and JavaScript day43-Feedback Ui Design(反馈ui设计) 效果 index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport&q…...
TypeScript基础篇 - TS日常类型 上篇
目录 TS的常见用法介绍 example01.ts 逃避类型检查:any 思考一下~:不知道类型 类型标注 函数(参数和返回值) 匿名函数 TS如何知道匿名函数的类型? TS是一种标注式语言,不侵入JS的设计 TS的常见用法…...
量化交易——python数据分析及可视化
该项目分为两个部分:一是数据计算,二是可视化,三是MACD策略 一、计算MACD 1、数据部分 数据来源:tushare 数据字段包含:日期,开盘价,收盘价,最低价,最高价,…...
微服务网关
1.网关是如何演化来的,在微服务中有什么作用? 随着单体架构转化为微服务架构的时候,由一个后台服务由一个单一的服务变成了多个微服务,前端应用需要调用多个服务的接口,为了解决这个问题,网关就产生了。网…...
【打卡】Datawhale暑期实训ML赛事
文章目录 赛题描述任务要求数据集介绍评估指标 赛题分析基于LightGBM模型Baseline详解改进baseline早停法添加特征 赛题描述 赛事地址:科大讯飞锂离子电池生产参数调控及生产温度预测挑战赛 任务要求 初赛任务:初赛提供了电炉17个温区的实际生产数据&…...
【python脚本】python实现:目标检测裁剪图片样本,根据类标签文件进行裁剪保存
python实现:目标检测裁剪图片样本,根据类标签文件进行裁剪保存 我在进行目标检测时候,比如红绿灯检测,目标区域很小,样本杂乱。 想要筛选错误样本的话,很困难。可以把目标区域裁剪出来。人大脑处理对于这…...
Mac 终端美化显示
Linux 也可安装 Zsh 后使用此套配置。 1. 安装 Oh My Zsh sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"2. 更换主题,修改文件:~/.zshrc,原内容: ZSH_THEME&quo…...
信息安全:密码学基本理论.
信息安全:密码学基本理论. 密码学是研究编制密码和破译密码的技术科学。研究密码变化的客观规律,应用于编制密码以保守通信秘密的,称为编码学;应用于破译密码以获取通信情报的,称为破译学,总称密码学. 目录…...
【linux升级ssh】 利用rpmbuild工具对ssh打包为rpm包进场安装升级
制作rpm包 rpmbuild命令用于创建软件的二进制包和源代码包。 官方文档:rpm.org - RPM Reference Manual rpmbuild 中文手册:rpmbuild 中文手册 [金步国] 使用rpmbuild将tar包打成rpm包 RPM打包使用的是rpmbuild命令,这个命令来自rpm-buil…...
UCloud上线可商用LLaMA2镜像,助力AGI应用发展
随着人工智能技术的快速发展,大模型应用在自然语言处理、图像识别、智能交互等领域展现出了巨大的潜力,为企业带来了更多创新和商机。众多企业纷纷将大模型应用于产品开发和业务优化中,希望通过提升智能化水平和用户体验来赢得竞争优势。近日…...
Linux推出Debian 12.1,并进行多方面系统修复
据了解,Debian是最古老的 GNU / Linux 发行版之一,也是许多其他基于 Linux 的操作系统的基础,包括 Ubuntu、Kali、MX 和树莓派 OS 等。 此外,该操作系统以稳定性为重,不追求花哨的新功能,因此新版本的发布…...
Spring 事务的使用、隔离级别、@Transactional的使用
Spring事务是Spring框架提供的一种机制,用于管理应用程序中的数据库事务。 事务是一组数据库操作的执行单元,要么全部成功提交,要么全部失败回滚,保证数据的一致性和完整性。 Spring事务提供了声明式事务和编程式事务两种方式&am…...
Top命令
Top top - 12:46:01 up 2 days, 11:10, 3 users, load average: 0.56, 0.59, 0.45系统基本信息:显示了系统运行时间、登录用户数和平均负载(load average)情况。平均负载是系统在特定时间范围内的平均活跃进程数,可以用来衡量系…...
(三)RabbitMQ七种模式介绍与代码演示
Lison <dreamlison163.com>, v1.0.0, 2023.06.22 七种模式介绍与代码演示 文章目录 七种模式介绍与代码演示四大交换机四种交换机介绍 工作模式简单模式(Hello World)工作队列模式(Work queues)订阅模式(Publis…...
ElasticSearch Java API 操作
1.idea创建Maven项目 2.添加依赖 修改 pom.xml 文件 <dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.8.0</version></dependency><!-- elasticsearch 的客户端 --…...
Linux信号机制:原理、处理与实践
1. Linux信号机制基础解析在Linux系统中,信号是一种进程间通信的重要机制。想象一下你正在厨房做饭,突然门铃响了——这个门铃就相当于Linux系统中的信号,它打断了你当前的工作流程,迫使你做出响应。信号本质上是一种异步事件通知…...
深入解析 iOS 上 fixed 底栏与滚动容器的手势冲突:从 H5 修复到原生根治
在移动端 H5 开发中,我们时常遇到这样的场景:页面底部有一个固定定位(position: fixed)的按钮栏或底栏,上方是一个可滚动的长列表。在 iOS 设备上,当用户尝试从底部 fixed 区域起手向上滑动时,列表却纹丝不动,仿佛被“粘”住了。这个现象不是偶发 bug,而是 iOS 对 fix…...
实战分享:如何用Altium Designer高效搞定PCB的定位孔、散热孔和屏蔽孔?
Altium Designer实战:PCB定位孔、散热孔与屏蔽孔的高效设计指南 在PCB设计领域,机械孔的设计往往被工程师视为"简单任务"而草率处理,直到量产时才发现定位偏差、散热不足或EMI超标等问题。作为从业十年的硬件设计师,我曾…...
Phi-4-mini-reasoning应用场景:AI编程教练中算法题逻辑拆解与反馈生成
Phi-4-mini-reasoning应用场景:AI编程教练中算法题逻辑拆解与反馈生成 1. 模型介绍 Phi-4-mini-reasoning是一款专注于推理任务的文本生成模型,特别擅长处理需要多步逻辑分析的场景。与通用聊天模型不同,它被设计用来解决数学题、逻辑题等需…...
NaViL-9B图文理解教程:从上传图片到获取结构化描述的完整步骤
NaViL-9B图文理解教程:从上传图片到获取结构化描述的完整步骤 1. 认识NaViL-9B多模态模型 NaViL-9B是一款原生支持多模态交互的大语言模型,能够同时处理文本和图像信息。与传统的纯文本模型不同,它可以直接"看懂"图片内容&#x…...
TFT LCD屏幕硬件解析:从XPT2046触摸屏到背光控制的完整指南
TFT LCD屏幕硬件解析:从XPT2046触摸屏到背光控制的完整指南 在工业控制面板和医疗设备显示屏等专业领域,TFT LCD屏幕凭借其高精度显示和可靠触控性能成为首选方案。不同于消费级产品的通用设计,专业场景下的屏幕需要工程师深入理解从触摸采样…...
2026.3.31 TRO成功和解案例 案件号:25-cv-25717,1000美金和解Palmer律所3000美金索赔,沃尔玛店铺全额解冻!
TRO经典案例案件概述案件号:25-cv-25717(点击查看案件详情)案件时间:2025-12-8收到TRO时间:2025-12-20销售平台:沃尔玛冻结金额:$209美金Palmer律所索赔额:$3,000美金侵权产品销售量…...
CHORD-X构建自动化运维报告系统:服务器日志分析与日报生成
CHORD-X构建自动化运维报告系统:服务器日志分析与日报生成 最近和几个运维朋友聊天,发现他们每天都要花一两个小时写日报、周报。服务器状态、错误日志、性能趋势……这些数据分散在各个系统里,手动整理起来特别费劲。关键是,这种…...
告别手动处理:用快马AI一键生成你的专属批量链接效率工具
最近在整理项目文档时,经常需要处理大量杂乱无章的链接。手动一个个检查、格式化这些链接不仅耗时耗力,还容易出错。于是我开始寻找更高效的解决方案,最终在InsCode(快马)平台上快速实现了一个批量链接处理工具,整个过程比想象中简…...
QMCDecode:让音乐自由播放的开源格式转换工具
QMCDecode:让音乐自由播放的开源格式转换工具 【免费下载链接】QMCDecode QQ音乐QMC格式转换为普通格式(qmcflac转flac,qmc0,qmc3转mp3, mflac,mflac0等转flac),仅支持macOS,可自动识别到QQ音乐下载目录,默认转换结果存…...
