超完整的Electron打包签名更新指南,这真是太酷啦!

linbojue
• 阅读 1974

大家好,我是多喝热水。

在踩了数不清的坑之后,终于从 0 到 1 完成了一个桌面端应用,但万万没想到,最最痛苦的还不是开发过程,而是开发完成后的打包签名阶段,这真是踩坑踩麻了!!!

超完整的Electron打包签名更新指南,这真是太酷啦!

ok,踩坑归踩坑,收获也是不小的,所以这篇文章会介绍一个 Electron 应用如何从 0 到 1 完成打包 & 签名 & 自动更新 等一系列流程,全程干货,建议点赞收藏!

目录
写在前面 一、打包 MacOS 平台打包 Windows 平台打包 二、代码签名 不做代码签名会遇到哪些限制? MacOS 代码签名 & 公证

  1. 加入苹果开发者
  2. 生成签名证书
  3. 安装签名证书
  4. 打包 & 签名
  5. 公证 Windows 代码签名
  6. 购买签名证书
  7. 安装签名证书
  8. 打包 & 签名 三、自动更新 为什么要做自动更新? 如何实现自动更新? 完结 写在前面 文章中所使用的环境如下,读者可作参考:

1)nodejs 版本:v18.19

2)electron 版本:v27.1.0

3)electron-builder 版本:v24.6.4

4)electron-rebuild 版本:v3.2.9

5)electron-notarize 版本:v1.2.2

6)electron-updater 版本:v6.1.4

7)node-abi 版本:v3.52.0

大家也可以根据自己安装的 Electron 版本来安装对应的 Node 版本,两者必须对应上,否则打包必出错,参考官方文档。

一、打包 打包有一个非常重要的前提,那就是安装包和系统对应,比如我想打包MacOS的安装包,那么我就需要使用 MacOS 电脑,Windows 同理,如果你没有,那你可以考虑安装一个虚拟机来打包。

MacOS 平台打包 1)准备好electron-builder配置文件,如下,具体的参数含义可参考官方文档

const path = require('path'); const fs = require('fs');

module.exports = async function () { function findFilesInDirectory(directoryPath, result = []) { const files = fs.readdirSync(directoryPath); files.forEach(file => { const filePath = path.join(directoryPath, file); const stats = fs.statSync(filePath); if (stats.isFile()) { result.push({from: filePath, to: '.'}); // 将主进程中用到的静态资源输出到打包后的软件根目录 } else if (stats.isDirectory()) { result = findFilesInDirectory(filePath, result); } }); return result; } const staticResources = findFilesInDirectory(path.join('packages', 'main', 'resources')); return { asar: true, // 代码加密 productName: '【软件名称】', compression: 'maximum', // 压缩代码 directories: { output: dist, // 将打包产物输出到dist文件 }, files: ['packages//dist/'], extraResources: [...staticResources], mac: { target: ['dmg'], icon: 'buildResources/icon.icns' // 软件图标 }, dmg: { icon: 'buildResources/icon.icns', iconSize: 100, } }; }; 2)应用中是否用到了 C / C++ 编写的依赖包?如果没有那么可忽略此步骤,如果有,那么需要使用 electron-rebuild 对 node_modules 预构建一次,且构建会需要用到 node-gyp(确保是最新版本的)+ Python 环境(Mac 自带的即可),运行命令如下:

electron-rebuild 3)配置 package.json 中的运行脚本

"scripts": { "build": "npm run build:main && npm run build:preload && npm run build:renderer", "build:main": "cd ./packages/main && vite build", // 主进程代码打包 "build:preload": "cd ./packages/preload && vite build", // 预渲染进程代码打包 "build:renderer": "cd ./packages/renderer && vite build", // 渲染进程代码打包 "compile": "rm -rf ./dist && npm cache clean --force && cross-env MODE=production npm run build && electron-builder build --config 【上面编写的配置文件名称】", }, 4)开始打包

npm run compile 打包完成之后我们就会看到生成一个 dist 文件夹,里面包含了一个 dmg 安装包和一些 yml 文件,此时我们就完成了第一步,如果你失败了,那么大概率是网络问题,可以重新打包,必要时清理一下 npm 缓存。

超完整的Electron打包签名更新指南,这真是太酷啦!

Windows 平台打包 1)windows 打包命令和 MacOS 一致,不同的是 electron-builder 的配置,我们对 electron-builder 配置文件进行改造,如下:

const path = require('path'); const fs = require('fs');

module.exports = async function () { function findFilesInDirectory(directoryPath, result = []) { const files = fs.readdirSync(directoryPath); files.forEach(file => { const filePath = path.join(directoryPath, file); const stats = fs.statSync(filePath); if (stats.isFile()) { result.push({from: filePath, to: '.'}); // 将主进程中用到的静态资源输出到打包后的软件根目录 } else if (stats.isDirectory()) { result = findFilesInDirectory(filePath, result); } }); return result; } const staticResources = findFilesInDirectory(path.join('packages', 'main', 'resources')); return { asar: true, // 代码加密 productName: '【软件名称】', compression: 'maximum', // 压缩代码 directories: { output: dist, // 将打包产物输出到dist文件 }, files: ['packages//dist/'], extraResources: [...staticResources], nsis: { oneClick: false, perMachine: false, allowToChangeInstallationDirectory: true, deleteAppDataOnUninstall: false, }, win: { icon: 'buildResources/icon.ico', // 软件图标 target: [ { target: 'nsis', // 使用 NSIS 进行打包 arch: ['x64'], }, ], }, }; }; 2)接下来的步骤与MacOS一致,这里不过多赘述,如下:

electron-rebuild 3)开始打包

npm run build 打包完成你可以在dist文件夹中看到如下文件和安装包:

超完整的Electron打包签名更新指南,这真是太酷啦!

此时我们已经完成了第一步,接下来我们需要对软件进行代码签名。

二、代码签名 代码签名需要哪些前置条件?

Windows 平台:购买EV证书,它可以立刻消除警告,但是这个证书非常昂贵,基本上都是 2000+的价格,且有效期只有一年

MacOS 平台:加入苹果开发者,价格是 99 美元,约为人民币 600+,同样有效期为一年

所以我们光签名就已经花费了 3000 左右,可能有些人在这里就已经劝退了,那不签名行不行?

不做代码签名会遇到哪些限制? 试想一下,你有一包辣条,但是你不知道这包辣条是哪个厂家生产的,你大概率会选择不吃!但如果辣条包装上有生产厂家和生产日期等信息,你吃起来是不是就更放心了?软件签名的道理也是如此!

1)在浏览器下载完这个软件的时候你可能会看到以下警告(图片出自网络),这样一个提示肯定是不利于传播的,如果是我,我可能会选择删除。。

超完整的Electron打包签名更新指南,这真是太酷啦!

2)即使下载后打开应用,你依然可能遇到如下问题(大致意思就是建议用户不要打开该软件,因为它是未知的开发者发布的)

超完整的Electron打包签名更新指南,这真是太酷啦!

3)在 MacOS 提示更为严重的软件损坏(直接就不让打开了,我辛辛苦苦开发的软件不让人用这还搞个毛线啊),如下:

超完整的Electron打包签名更新指南,这真是太酷啦!

MacOS 代码签名 & 公证 苹果签名的大致步骤拆分如下,更详细步骤移步 Electron 官网 代码签名 | Electron

1)加入 苹果开发者 (需要缴纳年费)

2)生成 & 下载签名证书,然后安装到本机, 苹果签名证书下载地址

3)打包签名后进行公证(不公证仍然会提示软件已损坏)

  1. 加入苹果开发者 1)点击苹果开发者注册地址,进入登录自己的 AppleID,然后就会看到如下界面:

超完整的Electron打包签名更新指南,这真是太酷啦!

2)点击注册,会让下载一个软件 Apple Developer,如下图:

超完整的Electron打包签名更新指南,这真是太酷啦!

3)打开Apple Developer 去注册苹果开发者,如下:

超完整的Electron打包签名更新指南,这真是太酷啦!

4)点击立即注册,如下:

超完整的Electron打包签名更新指南,这真是太酷啦!

5)按要求填写信息,如下:

这里需要注意,如果是以公司的名义去注册的,那么你还需要注册一个邓白氏编码(D-U-N-S),在后续会用到。

超完整的Electron打包签名更新指南,这真是太酷啦!

  1. 生成签名证书 1)注册完成后,我们打开本机电脑的钥匙串访问 => 证书助理 => 从证书颁发机构请求证书,如下:

超完整的Electron打包签名更新指南,这真是太酷啦!

2)填写邮箱,并选择存储到磁盘,如下:

超完整的Electron打包签名更新指南,这真是太酷啦!

3)点击继续之后就会创建一个证书,提示存储到哪里,我们先存储到桌面上

超完整的Electron打包签名更新指南,这真是太酷啦!

4)前往苹果开发者官网申请 Developer ID Application(需要用到我们刚才请求的证书,此步骤需要账户持有人操作)

点击 Choose File,上传我们之前在自己电脑上申请的证书文件,上传完成后我们就可以得到Developer ID Application 证书,将它下载保存到桌面。

超完整的Electron打包签名更新指南,这真是太酷啦!

  1. 安装签名证书 1)将下载到桌面的证书拖拽到钥匙串访问的证书列表中,并将 私钥 导出为 .p12 文件

超完整的Electron打包签名更新指南,这真是太酷啦!

2)打开终端配置环境变量,此处参考的是 electron-builder 官方文档

超完整的Electron打包签名更新指南,这真是太酷啦!

3)输入如下两个环境变量,对应的是 p12 文件的地址和证书对应的密码,配置完成后使用 source 命令让刚才配置的环境变量生效

超完整的Electron打包签名更新指南,这真是太酷啦!

4)输入 env 查询是否配置成功,如果显示了我们填写的环境变量地址,那就成功了

超完整的Electron打包签名更新指南,这真是太酷啦!

  1. 打包 & 签名 在做完以上操作后,目前你不需要对 electron-builder 配置做任何更改,直接可以运行打包命令,在打包过程中你会看到如下 signing 正在签名的提示,如下:

超完整的Electron打包签名更新指南,这真是太酷啦!

验证是否签名,你可以在软件包内容中你可以看到 _CodeSignature 的文件夹,表示该应用已经被成功签名了,如下:

超完整的Electron打包签名更新指南,这真是太酷啦!

  1. 公证 苹果平台除了签名,还需要进行公证,两者缺一不可,公证我们需要用到 electron-notarize 这个包,具体的配置如下:

1)appbundleId:在苹果开发者中注册的应用 ID

2)appPath:固定写法,照抄即可

3)appleId:苹果开发者的苹果 ID

4)appleIdPassword:临时密码生成地址,临时密码需要保存好,因为关掉后它不会再显示了

超完整的Electron打包签名更新指南,这真是太酷啦!

5)ascProvider:团队 ID 查看地址

超完整的Electron打包签名更新指南,这真是太酷啦!

6)tool:签名工具,公证工具

7)teamId:团队 ID 同 ascProvider

buildResources/notarization/notarize.js

const {notarize} = require('electron-notarize');

exports.default = async function notarizing(context) { const {electronPlatformName, appOutDir} = context; if (electronPlatformName !== 'darwin') { return; } const appName = context.packager.appInfo.productFilename; // console.log(打包后应用地址:${appOutDir}/${appName}.app); return await notarize({ appBundleId: 'com.xxx.xxx', appPath: ${appOutDir}/${appName}.app, //打包后的放置app文件的命名和路径【固定写法】 appleId: 'xxx@qq.com', appleIdPassword: 'xxxx', // 临时密码 ascProvider: '团队ID', tool: 'notarytool', // 公证工具 固定写法 teamId: '团队ID', }); }; .electron-builder.config.js

在 afterSign 选项中加入我们公证逻辑的地址,该字段表示打包完成之后进行公证

超完整的Electron打包签名更新指南,这真是太酷啦!

加完这些配置之后再次重新打包即可完成公证!

Windows 代码签名 windows 签名也比较简单,但是在 Windows 上花费的时间不比苹果少,这里建议大家不要去开微软开发者,如果你不打算把软件分发到微软商店的话,那开通微软开发者对签名没有什么帮助,这也是我们花费了 99 刀踩过的坑!

  1. 购买签名证书 现在的签名证书都是以 U 盾的形式发放(快递邮寄,一般都是国外发货),没有数字签名了,这里我调研了很多平台,确信!建议从淘宝代理那购买 Sectigo EV 代码签名证书,比较便宜。

  2. 安装签名证书 1)安装 SafeNet Authentication Client 软件,这个软件是用来安装证书的,安装地址。

2)插入包含签名证书的 U盾,然后我们就会在软件左侧看到对应的证书信息

超完整的Electron打包签名更新指南,这真是太酷啦!

3)安装签名证书

超完整的Electron打包签名更新指南,这真是太酷啦!

选择安装到当前用户或本机都可以,最终我们选择安装到受信任的根证书颁发机构

超完整的Electron打包签名更新指南,这真是太酷啦!

4)导出签名证书 cer 文件到桌面

我们使用 Win + R 唤出如下界面,并输入 certmgr.msc

超完整的Electron打包签名更新指南,这真是太酷啦!

找到我们的证书所在位置

超完整的Electron打包签名更新指南,这真是太酷啦!

右键导出 cer 文件到桌面

超完整的Electron打包签名更新指南,这真是太酷啦!

5)打开签名软件的设置页,设置单点登录(因为等会打包会涉及到多次密码输入,为了简化流程)

超完整的Electron打包签名更新指南,这真是太酷啦!

6)初始密码太繁琐了,我们可以修改一下证书的初始密码( Token Password ),这个证书的初始密码可以在你购买时填写的邮箱中找到

超完整的Electron打包签名更新指南,这真是太酷啦!

7)找到我们导出的证书文件,现在是 cer 格式的,我们需要将它 重命名为 pfx 格式,因为 electron 打包只支持 pfx 格式的文件

  1. 打包 & 签名 将 certificate.pfx 文件拖入项目根目录,在electron-builder中加入如下配置:

return { appId: 'com.xxx.xxx', nsis: { oneClick: false, perMachine: false, allowToChangeInstallationDirectory: true, deleteAppDataOnUninstall: false, }, win: { icon: 'buildResources/icon.ico', verifyUpdateCodeSignature: true, // 更新校验签名 signingHashAlgorithms: ['sha256'], signAndEditExecutable: true, signDlls: false, publisherName: '上海xxxx有限公司', certificateSubjectName: '', rfc3161TimeStampServer: 'http://timestamp.sectigo.com', target: [ { target: 'nsis', // 使用 NSIS 进行打包 arch: ['x64'], }, ], certificateFile: 'certificate.pfx', // 我们导出的证书 certificatePassword: 'xxxxxx', // 上面我们修改的密码 }, mac: { // ... }, dmg: { // ... } }; }; 现在可以执行打包命令,打包过程中你会看到 signing 正在签名的提示,打包结束为了验证是否完成签名,你可以右键打包出来的exe产物,查看数字签名栏的信息,如果显示的是你填写的 publisherName 字段值,那么表示签名成功,如下: 超完整的Electron打包签名更新指南,这真是太酷啦!

超完整的Electron打包签名更新指南,这真是太酷啦!

三、自动更新 为什么要做自动更新? 用户下载了你的软件,如果每次都需要去官网下载更新的话,那么久而久之用户必然会觉得很烦,甚至产生卸载软件的念头,所以我们需要做的就是将用户手动去下载更新这个操作自动化,换成自动下载安装包完成更新。

如何实现自动更新? 1)我们需要用到 electron-updater 这个包,主要需要用到 autoUpdater 这个对象

import { type BrowserWindow } from 'electron'; import { autoUpdater } from 'electron-updater'; import { createModalWindow } from './windows/modal';

/**

  • 自动更新检测

  • / export const checkUpdate = () => { // 创建设置窗口 function updateAvailable() { // 创建有新版本的弹窗提示 createModalWindow(); } // function updateDownloaded() { // 安装包下载完成,将自动安装,给出提示... // ... } // 开启自动安装 & 自动下载 autoUpdater.autoInstallOnAppQuit = true; autoUpdater.autoDownload = true;

    if (process.platform === 'darwin') { // 苹果平台【interl/M系列区分】 const ARM = process.arch == 'arm64'; const feedUUL = ARM

    ? 'https://xxxx.com/installer/mac/arm'
    : 'https://xxxx.com/installer/mac/intel';

    autoUpdater.setFeedURL(feedUUL); } else { // windows平台 autoUpdater.setFeedURL('https://xxxx.com/installer/win'); } // 检测新版本 autoUpdater.checkForUpdatesAndNotify().catch(); // 发现可用的安装包 autoUpdater.once('update-available', updateAvailable); // 安装包下载完成了 autoUpdater.once('update-downloaded', updateDownloaded); }; 2)在 .electron-builder.config.js 中加入 publish 字段,用于检测当前地址中latest.yml文件记录的版本

在加入了publish字段后我们再打包会生成一个latest.yml文件(苹果是latest-mac.yml),该文件我们需要上传到自己的安装包所在的目录,检测新版本就是检测 latest.yml文件中记录的版本

超完整的Electron打包签名更新指南,这真是太酷啦!

latest.yml 文件格式

超完整的Electron打包签名更新指南,这真是太酷啦!

完结

https://www.720yun.com/vr/03ejzskf5k2 https://www.720yun.com/vr/1edjzskf5m8 https://www.720yun.com/vr/467jzskf5n2

好了,到这里整个流程就算是跑完了,大家有不懂的可以在评论区讨论,文章哪里有写的不好的欢迎大佬指点,我太想进步了!!🥹

点赞
收藏
评论区
推荐文章
海军 海军
3年前
Vue权限路由[菜单权限/按钮权限控制]
前言&nbsp;&nbsp;&nbsp;年前完工了做了半年的铁路后台管理系统,系统整体业务比较复杂,这也是我到公司从0到1的一个完整系统实践,做这个系统过程中踩了不少坑,也学到了很多。</br&nbsp;做完这个系统没多久,紧接着又一个系统来了,没及时总结,惭愧哈!其实我们在做的后台管理系统大多数基础框架都一样,后台管理系统主要的是
代码哈士奇 代码哈士奇
2年前
vite+vue3+electron桌面端开发
vitevue3electron桌面端开发ps:踩坑踩了一个多小时如果嫌麻烦可以直接拿走用克隆代码仓库1.2.同样你也可以使用脚手架来快速的创建如下图是生成的安装包选择了mis和nsis安装使用下载代码后进入项目目录执行npminstall安装依赖执行npmstart为开发模式执行npmdist为打包项目并且生成
学python的猫 学python的猫
3年前
这些常见的坑,90%的程序猿都踩过,来看看里面有没有你的脚印?
在学习python的过程中,相信大家都有踩过不少的坑,有些坑可能踩了不止一次,感觉就像是在坑与坑之间反复横跳。那么如何避免这些坑呢?看完这篇文章,你就知道了。我们来谈谈我们学习python的过程中,最常见的七大坑:1.缩进,符号和空格不正确写代码时大家会使用缩进、对齐、空格等,这些是为了提高代码的可读性在python语言中,缩进是十分重要的比如在创建一个新
Easter79 Easter79
3年前
toLua踩坑
新博客:https://yinl.fun(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fyinl.fun)欢迎关注,同步更新toLua踩坑篇最近工作得用Lua实现逻辑,桥梁用的toLua,踩了很多坑,在这里记录一下。坑~toLua解析Lua属性
Stella981 Stella981
3年前
Groovy防PermOOM与OldOOM心得
作为Groovy重度用户,踩了新版本因为无法unloadclass导致permoom的坑,踩了classLoader.parallelLockMap不断添加新锁导致oldoom的坑。本文的意图就是记录一点埋坑心得。踩坑详情可见:https://my.oschina.net/chenxiaojie/blog/835934(https://my.o
Stella981 Stella981
3年前
Electron桌面端所见即所得
突然让你开发Electron应用,你能hold住吗?如果领导突然说需要开发一款前端桌面端应用,那么对于我们前端er来说选择Electron是一件顺理成章的事情。但事实上很多同学对于Electron都不太了解和熟悉。如果突然让我们去开发Electron应用,很多人都会陷入迷茫和懵逼的状态。然后在依靠网上相对较少的资料,慢慢摸索、一路踩坑
Stella981 Stella981
3年前
Electron踩坑记录
心血来潮想做一个PC端应用,就来学学Electron,以下为学习Electron时的踩坑记录。心血来潮想做一个PC端应用,就来学学Electron,以下为学习Electron时的踩坑记录。安装在国内安装electron的时候,可能会因为网络原因遇到卡在Buildingfreshpackages...(yarn)或者是卡在nod
Stella981 Stella981
3年前
Node.js 中使用 ECDSA 签名遇到的坑
文/Fenying最近有个朋友问我关于Node.js下使用ECDSA的问题,主要是使用Node.js的Crypto模块无法校验网络传输过来的签名结果。在踩坑无数后,终于搞清楚了原因。坑0x00:签名输出格式在排除了证书、消息不一致的可能之后,我开始对比使用Node.js签名的结果与网络传输过来的签
Stella981 Stella981
3年前
Copy攻城狮辛酸史:含泪“一分钟”跑通MindSpore的LeNet模型
摘要:一个Cope攻城狮用切身实例告诉你:Cope代码体验一时爽,BUG修改花半天。前言:此文为r0.7beta的操作实践,为什么我的眼里常含泪水,因为我对踩坑这件事爱得深沉。谨以此文献给和我一样踩坑的小伙伴,纪念踩坑时刻。!(https://pic2.zhimg.com/80/v20c653151d9ddd33a2a2622
聊聊Spring注解@Transactional失效的那些事 | 京东云技术团队
emm,又又又踩坑啦。这次的需求主要是对逾期计算的需求任务进行优化,现有的计算任务运行时间太长了。