尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Electron Windows 打包实战:从 electron-builder 到 native 模块的踩坑全记录

Electron Windows 打包实战:从 electron-builder 到 native 模块的踩坑全记录 1. 打包方案选型选错工具后面全是泪1.1 electron-builder 与 electron-forge 的抉择先聊一个很多人一开始没意识到的问题Electron 应用“能跑起来”和“能打包交付”完全是两码事。开发模式下 Vite 起了热更新、主进程开着 devtools一切都很美好但到了要交差的时候Windows 用户拿到的应该是.exe安装包最好还是双击就能装完的那种。这时候你手头的工具决定了接下来是顺风顺水还是加班地狱。目前主流方案就是两套electron-builder和electron-forge。还有一些人直接用electron-packager但它只能解压 Electron 二进制、替换应用文件连安装包都不会生成Windows 场景下基本不够用我直接不推荐。electron-forge是 Electron 官方的脚手架工具整合了 make、publish 等流程理念上更“官方”但目前对 Windows 安装包的定制能力相对较弱NSIS 相关的内置配置也不够细。而electron-builder虽然是社区主导但它对多平台打包win/mac/linux的支持极其成熟对 NSIS、WiX、AppX、Portable、Squirrel.Windows 都有完善适配文档虽然有点乱但配置项覆盖面广到令人发指。我的建议很直接Windows 平台打包优先选electron-builder。它帮你干掉了大部分脏活而且生态里踩坑记录最多遇到问题 Google 一下基本都有答案。Forge 更适合做项目脚手架统一管理但如果你已经跑在 Vite electron-builder 的路子上别折腾换工具了问题不在工具在于配置没吃透。1.2 我在 Windows 上选型时的几个判断标准选 electron-builder 不只是因为名气大我实际对比过之后发现几个不可替代的优势。第一它对 Windows 安装包类型的支持非常完整。NSIS 可以定制安装界面、协议页、快捷方式还能做 one-click 安装Portable 模式适合做个免安装的绿色工具MSI 则适合企业批量分发。electron-forge 对 MSI 的支持目前在 Windows 上还比较绕如果你处在企业内网环境下需要组策略分发 MSIelectron-builder 几乎是保证不卡壳的选择。第二它的依赖处理策略很聪明。打包时会自动把dependencies里用到的原生模块重新编译到当前 Electron 版本对应的 ABI不需要你手动挨个node-gyp rebuild。这也是后面专门要讲 native 模块处理的原因electron-builder 把 70% 的工作自动化了剩下的 30% 需要你理解它为什么这么做。第三多平台构建的体验趋于一致。虽然这篇博文聚焦 Windows但项目到了后面大概率要出 macOS 或 Linux 包electron-builder 的配置可以共用一份 YAML只需要把不同平台的差异化参数写清楚就行。将来即使你只维护 Windows也给自己留了后路。判断标准说白了就三条能否覆盖当前需求、原生模块处理是否自动化、后期扩展是否轻松。三条对比下来electron-builder 在 Windows 平台上就是最不容易出意外的那一个。2. Windows 平台特有的坑Mac 上完全体会不到2.1 代码签名Windows 的“门禁”比其他系统严格macOS 也有签名和公证但坦白说Windows 的“恐吓式”安全机制才是最容易让新手心态崩掉的环节。你辛辛苦苦打包出一个安装程序放到 Windows 10/11 上一跑SmartScreen 直接弹蓝屏提示“Windows 已保护你的电脑”甚至一些杀毒软件直接把 exe 文件当木马删了。这个问题的根子在于Windows 对未知发布者有着极其严格的不信任策略。你没有代码签名证书系统就认为你的应用是“来路不明的”宁可误杀也不放行。这跟你的代码写得好不好完全无关纯粹是没有签名惹的祸。解决办法分生产环境和测试环境两种。生产环境要么买商业证书要么买 OVOrganization Validation或 EVExtended Validation证书。EV 证书最贵但能立刻建立 SmartScreen 信任OV 证书便宜一些需要积累信誉用户第一次运行时仍然可能看到提示只是多了“仍要运行”的选项。个人开发者也可以选 Individual Validation 证书能签名但 Windows 的信任度更低。测试环境就别花冤枉钱了直接用自签名证书。Windows 下用 PowerShell 的New-SelfSignedCertificate可以生成一个测试用证书然后配合signtoolWindows SDK 自带做签名。需要注意的是自签名证书不仅要在签名时用到还需要把这颗证书导入到测试机器的“受信任的根证书颁发机构”存储区不然照样报“未知发布者”。签名命令本身不复杂但有一个细节特别容易踩坑现代 Windows 系统要求双签名即 SHA1 和 SHA256 两个签名同时存在老系统认 SHA1新系统认 SHA256。如果只签一个大概率会在某个版本的 Windows 上翻车。electron-builder 在配置了证书文件后会自动处理双签名但如果走手动脚本signtool sign要跑两遍用/as参数追加第二个签名。2.2 杀软误报与 SmartScreen杀毒误报这个话题做 Windows 桌面端的人基本都经历过。常见的误报来源有三个Electron 框架本身的特征被启发式引擎盯上了、安装包 NSIS 脚本的行为模式与某些恶意软件相似、应用如果没签名则更容易被重点照顾。先说启发式误报。某些国产杀软和国外的 AVG、Avast 对 NSIS 安装包特别敏感因为 NSIS 脚本一旦逻辑复杂行为特征就会跟捆绑类病毒有点像。这是玄学但也不是完全没办法缓解保持配置干净尽量少做“安装时下载额外文件”这种操作能降低误报概率。然后是 SmartScreen。就算被杀软放过了Windows 的 SmartScreen 也会拦一道尤其是新发布的未签名应用。SmartScreen 会根据文件签名、下载来源、用户举报记录做综合判断。一个新应用如果没人运行过信誉是零第一次运行必然提示。处理路径有几条一是买签名并等待信誉积累让用户多运行、少举报二是走微软的“Windows 应用提交”流程做签名认证这个门槛高普通开发者基本不需要三是给用户写清楚引导文案告诉他们如何手动选择“仍要运行”。实际交付项目时我一般会额外写一份《首次运行说明》把 SmartScreen、杀软加白、自签名证书导入三步都写清楚能省掉大量售后提问。还有一个很容易被忽略的点electron-builder默认打出来的安装包体积在七八十兆以上NSIS 解压时如果触发实时监控杀软速度会非常慢可能让人觉得“卡死了”。这种性能问题不是 bug杀软全盘扫描一个几十兆的 NSIS 安装包确实要花时间建议在说明文档里提示用户安装时暂时关闭实时监控或者至少有心理预期。2.3 图标资产一套 ICO 要走完所有尺寸打包窗口标题栏、任务栏、安装包图标、桌面快捷方式、开始菜单磁贴这些位置的图标系统并不会缩放同一张图给你用它会在 ICO 文件内部查找适合当前尺寸的目录项。如果你只塞了一张 256x256 的 PNG 转出来的 ICO那么桌面快捷键的小图标必然是糊的。最省心的方法是用 electron-builder 的图标自动化流程准备一张 1024x1024 的 PNG然后交给打包工具自动生成配套的 ICO。它会调用icon-gen或内置转换逻辑把不同尺寸16、24、32、48、64、128、256都生成好塞进 ICO。但这里有一个坑这个自动流程依赖系统是否有可用的转换库。更稳定的做法是手动生成Windows 上用 ICO 工厂或在线工具把多尺寸合成到一个文件。注意ICO 里不仅要有多尺寸还要设置压缩质量。我生成完成后会把 ICO 的属性面板打开检查一遍确认每个尺寸都在目录里。这一步虽然繁琐但真的能避免后期“换了个图标还是原来那个”的笑话。跟图标配套的还有两个地方窗口图标和任务栏图标。开发模式下你可能在 index.html 里引用了 favicon但打包后 Electron 主进程会使用BrowserWindow的icon参数如果你没在主进程里指定窗口左上角的图标在 Windows 上会显示默认的 Electron 外星人。即使安装包图标改好了运行时窗口图标不一定跟着变这个属于主进程配置问题跟打包配置是两套体系。正确做法是在创建BrowserWindow时显式传入icon: path.join(__dirname, ../build/icon.ico)。注意Windows 上推荐使用.ico而不是.png因为窗口标题栏尺寸小PNG 在某些 DPI 缩放下会出现边缘锯齿。2.4 系统依赖、路径与权限Windows 打包最容易被“环境问题”绊倒其中重点就是 VC 运行库和路径规范。Electron 应用本身自带了 Node.js 运行时大部分 JS 代码不需要额外的系统运行库但如果你在应用里用了某些 native 模块比如 serialport、sqlite3、robotjs它们编译出来后可能依赖 MSVC 运行库。目标机器如果没装 VC Redistributable模块加载就会报The specified procedure could not be found之类的错误。解决方案要么是在安装包里捆绑 VC 运行库安装器要么在文档里写清楚安装前置条件。路径问题是 Windows 的祖传毛病。electron-builder 的打包目录、输出目录、仓库路径都不能含中文和空格否则 NSIS 生成安装包时容易失败。我遇到过同事用中文用户名比如C:\Users\李雷\project跑打包electron-builder 在读取临时目录时直接崩掉。这个问题看起来老生常谈但在 Windows 环境里就是会反复遇到。最简单的办法是统一约定项目放在C:\workspace\project-name这种纯英文、无空格的目录里。权限问题主要体现在安装目录的选择上。NSIS 默认安装到Program Files但这个目录需要管理员权限才能写入而 Electron 应用如果配置了自动更新更新时可能因权限不足失败。这时 NSIS 配置里perMachine参数就非常重要设置成true表示所有用户共用需要管理员权限安装设置成false则默认安装到AppData\Local\Programs普通权限就能装。从避免权限烦恼的角度个人开发的小工具我更推荐perMachine: false。3. electron-builder 完整配置实操可直接抄作业3.1 推荐的目录结构与文件说明先给出一套我实际验证过很多遍的目录结构它让打包配置、构建产物和应用代码保持清晰隔离。project-root/ ├── build/ │ └── icon.ico ├── src/ │ ├── main/ │ │ └── index.js │ ├── preload/ │ │ └── index.js │ └── renderer/ │ └── (Vue/React 构建产物) ├── electron-builder.yml └── package.jsonbuild/目录除了放图标还可以放代码签名证书建议证书不要提交到 Git用环境变量引用、NSIS 自定义安装背景图和横幅图。src/main存放 Electron 主进程代码src/preload存放预加载脚本src/renderer则是渲染进程构建后的静态资源。electron-builder 默认会读取 package.json 里的main字段作为主进程入口构建完毕后把渲染进程的静态文件路径配置好即可。这里有个容易混乱的地方electron-builder 真正打进安装包的并不是开发源码目录而是“打包后的应用目录”。这个目录里的package.json不一定和你源码目录的完全一样它可以通过files字段做裁剪。如果你的主进程是经过打包工具比如 esbuild、tsup压缩后的单文件那你在files里只需要包含这个单文件以及依赖目录即可不需要塞进全部源码。3.2 package.json 里的关键字段package.json 是所有配置的起点我先标出跟打包强相关的字段。{ name: my-desktop-tool, version: 1.0.0, description: 一个内部自动化工具, main: dist/main/index.js, author: Your Name youexample.com, license: MIT, scripts: { dev: vite, build: vite build, pack:win: electron-builder --win --x64, pack:dir: electron-builder --dir }, devDependencies: { electron: ^30.0.0, electron-builder: ^24.13.3, vite: ^5.0.0 }, dependencies: { serialport: ^12.0.0 } }name和version会被直接用到安装包信息里author在 Windows 的 exe 文件属性中会显示为“公司名称”建议写成真实可识别的组织名。main字段必须指向打包后主进程文件的实际路径如果配错了应用打完包双击没有任何反应但开发模式却好好的那八成就是这个字段的问题。pack:win脚本里我加了--x64明确只构建 64 位避免同时构建 32 位导致的额外时间消耗。如果你需要兼容老机器再考虑--ia32但说实话现在 32 位 Windows 已经很少见了没必要默认双架构。3.3 electron-builder.yml 逐项解析electron-builder 支持把配置写在 package.json 的build字段里也支持独立 YAML 文件。我偏好独立 YAML因为配置多了之后写在 package.json 里会把文件撑得特别长而且 YAML 支持注释方便团队协作时解释每个参数的含义。下面是我在 Windows 项目里常用的一套配置我挑重点逐项拆解。appId: com.example.myapp productName: MyApp directories: output: release/ buildResources: build/ files: - dist/**/* - package.json asar: true win: icon: build/icon.ico target: - target: nsis arch: - x64 nsis: oneClick: false perMachine: true allowToChangeInstallationDirectory: true createDesktopShortcut: true createStartMenuShortcut: true shortcutName: MyApp installerIcon: build/icon.ico uninstallerIcon: build/icon.icoappId类似安卓的包名Windows 上会被写进注册表里用于识别安装实例。后期如果做自动更新appId 也参与更新逻辑的匹配建议一开始就确定不要随意改。productName是用户看到的软件名安装目录和开始菜单快捷方式都会用它。directories.output是打包产物输出目录默认是dist但我建议显式改成release避免和渲染进程 Vite 构建输出的dist目录混淆。两个 dist 是打包新人最容易搞混的地方。files字段用于指定要被打包进安装包的应用文件。这里只包含dist/**/*和package.json也就是说最终安装包里只有构建后的渲染进程资源、主进程代码和依赖声明。但等一下如果你的主进程代码用了serialport这样的 native 依赖光有 dist 目录和 package.json 还不够node_modules 会被单独处理这个后面会专门讲。asar: true默认开启。它会把应用文件打包成一个app.asar归档文件这样既能保护源码不被轻易看到又能减少文件碎片、提升启动速度。很多新手打包后打开应用目录发现根本没看到自己的代码文件只看到一个resources\app.asar这是正常的不需要惊慌。win.target里我只写了nsis这是 Windows 默认的安装包格式。electron-builder 还支持直接出portable免安装单文件或zip根据需求自行添加。多 target 的代价是构建时间翻倍所以基本按需配置。3.4 NSIS 安装包定制要点NSIS 是 electron-builder 在 Windows 上默认使用的安装程序框架它生成的安装包提供图形界面、快捷方式创建、卸载等能力。很多人想定制安装界面其实并不需要去写 NSIS 脚本electron-builder 已经提供了足够多的参数。先看安装模式。oneClick: false意味着安装向导会多几步选择安装目录、确认安装选项。这是企业内部分发时最常用的模式用户不会误操作也能自定义路径。perMachine: true表示安装到Program Files这需要管理员权限如果你的目标用户平时没有管理员权限建议改成false。allowToChangeInstallationDirectory: true配合非 oneClick 模式用户可以在安装向导里手动改目录。对于向普通用户分发的工具这个选项很友好强制装在 C 盘会让人反感。快捷方式方面createDesktopShortcut和createStartMenuShortcut控制是否创建桌面和开始菜单入口。注意NSIS 支持安装后自动运行程序但 electron-builder 的 NSIS 配置里没有直接打包成“安装完成后启动”的选项这个需要用自定义脚本或改 NSIS include 文件实现普通项目不需要纠结。卸载时是否清空用户数据是一个需要仔细思考的点。NSIS 默认卸载只删除程序文件位于app.getPath(userData)的用户配置并不会被清理。如果你希望卸载时把用户生成的本地数据也清掉需要额外编写 NSIS 宏或主进程处理。大部分应用都应该保留用户数据因为卸载重装后数据还在用户体验更好所以我一般不做清理。3.5 pnpm 用户必须注意的坑pnpm 现在越来越流行但它和 electron-builder 的组合在 Windows 上有一个非常经典的坑node_modules 的目录结构是软链接式的electron-builder 默认对 node_modules 的处理策略会因为它“目录不真实存在”而漏打包依赖。具体表现是打完包运行提示某个依赖找不到但在项目源码里跑却一切正常。原因就是 electron-builder 的依赖收集机制对 pnpm 的符号链接支持不完整。好在这套坑已经有成熟的应对方案了。在 package.json 里加上下面这段build: { buildDependenciesFromSource: true, npmRebuild: true }或者更彻底的方式build: { files: [ dist/**/*, node_modules/**/*, package.json ], asarUnpack: [ node_modules/**/* ] }把 node_modules 全量塞进 app 目录虽然后果是安装包体积膨胀但确实能规避 pnpm 的符号链接问题。如果不想这么做另一种方案是改用 npm 或 Yarn 作为打包时的包管理器或者干脆在 CI 里用 npm 重新执行一次 install。我这里提供一个更精细的解决思路在 package.json 的scripts里增加一个prepack钩子先用 pnpm 安装再调用 electron-builder 的node_modules分析逻辑。具体来说electron-builder 从v24.10.0开始对 pnpm 的 v9 lockfile 支持已经好很多了先把 pnpm 升级到最新版再在electron-builder.yml里配置npmRebuild: true buildDependenciesFromSource: true这样可以保证 native 模块被正确重建同时在绝大多数情况下能正常解析 pnpm 的虚拟依赖目录。如果项目还遇到了“打包后依赖缺失”的问题我后面会在排查章节再给出几条定位思路。4. native 模块、serialport 与运行时依赖的处理4.1 为什么 native 模块在打包时最容易炸Electron 的 native 模块麻烦之处在于它的底层是 Node.js 的 C 扩展用node-gyp编译出来的二进制文件跟目标 ABI 强绑定。Electron 内置的 Node.js 版本通常和系统上的 Node.js 不完全一致你在源码环境下编译出的.node文件放到 Electron 运行时里很可能因为 ABI 不匹配而加载失败。serialport 就是这类依赖的典型代表。热词里出现了electron serialport说明大家都在关心串口设备在 Electron 应用里怎么调起来。serialport 的核心是二进制原生模块serialport/bindings-cpp它跟 Node 版本、Electron 版本都有耦合。如果不做专门处理在 Electron 里require(serialport)会直接抛NODE_MODULE_VERSION 127 不匹配之类的错误。除了 serialport常见的 native 模块还有 sqlite3数据库、robotjs全局按键、node-pty伪终端、sharp图像处理等。凡是需要在打包后继续使用系统能力的模块都要纳入 native 模块的管理体系。4.2 electron-rebuild 与 install-app-deps 的正确用法现在处理 native 模块的标准做法是交给electron/rebuild。它能扫描项目里的原生依赖根据当前 Electron 版本重新编译它们。electron-builder 内置了同样的功能在打包时会自动执行 rebuild但你也可以在开发阶段手动触发。推荐在 package.json 里加两个脚本scripts: { rebuild: electron-rebuild -f -w serialport, postinstall: electron-builder install-app-deps }这里的postinstall是关键。每次执行npm install或pnpm install安装完依赖后自动调用electron-builder install-app-deps它会把项目里的原生依赖编译成当前 Electron ABI 兼容的版本。这样你在开发环境里运行 Electron 时serialport 就能正常加载。手动重建用electron-rebuild -f -w serialport-f强制重新构建所有依赖-w后跟需要重新构建的包名。如果项目里有多个 native 依赖可以不加-w让它全部重建但耗时会更长。到这里还没完打包之后还要确认 native 模块是否被正确打包进app.asar。这里有个关键机制Electron 无法从 asar 归档里直接加载 native 二进制文件因为 asar 是只读归档C 扩展需要物理文件存在于磁盘系统。所以 electron-builder 提供了asarUnpack配置asarUnpack: - node_modules/serialport/**/* - node_modules/serialport/**/*asarUnpack的意思是打包时把这些文件“解包”到app.asar.unpacked目录下asar 内的对应位置会写一个软链接或重定向逻辑Electron 能自动找到它们。少了这一步native 模块即使编译成功运行时也找不到动态库。我自己的习惯是只要是 native 依赖全部加入asarUnpack宁可让安装包大一点也不要冒着运行时崩掉的风险。serialport、sqlite3、robotjs 这些全都放进去。4.3 调试 native 模块加载失败的思路在 Windows 上调试 native 模块加载失败最直接的入口是打开开发者工具看主进程控制台。Electron 主进程在启动时如果require(serialport)抛错错误信息会直接打印在终端或日志里。常见的报错单词是NODE_MODULE_VERSION不匹配。这个报错说明编译时的 ABI 版本和运行时不一致解决办法就是重新 electron-rebuild。还有一种情况是.node文件本身编译成功了但依赖的 Windows 动态链接库如libusb-1.0.dll缺失或不在PATH里。serialport 在 Windows 上依赖libusb驱动如果目标机器装了精简版系统或者新装了系统可能缺少 USB 驱动这时就要提示用户安装正确的驱动或者把动态库一起放到extraResources里。还有一个经常被忽略的地方如果你的应用在打包后以 asar 方式运行native 模块加载失败报的错可能不是路径不存在而是Cannot find module这是因为 electron-builder 的依赖收集漏掉了某个二级依赖。排查时可以先用--dir模式打包一个未压缩的应用目录然后打开resources\app.asar.unpacked检查node_modules下是否真的有对应的.node文件层层排查。5. 高频问题排查实录这些错误我基本都踩过5.1 打包后白屏页面死活打不开这是 Vit/Webpack 打包完后最容易出现的问题。开发模式一切正常打包安装后启动应用窗口出来了但内容是白屏没有报错也没有任何界面元素。第一步要分辨是渲染进程加载失败还是主进程资源路径配置错误。打开开发者工具如果没有禁用查看 Console 里报什么错。最常见的是Not allowed to load local resource原因是在主进程里用相对路径加载了渲染进程文件。正确写法是win.loadFile(path.join(__dirname, ../dist/index.html));不要写win.loadURL(file:// __dirname /dist/index.html)在 Windows 上路径分隔符是反斜杠极容易拼出非法 URL。用loadFile配合path.join是最稳妥的。另一个白屏原因是渲染进程代码在打包后访问了某个运行时不存在的外部 API。比如开发环境下 Vite 代理帮你解决了跨域问题但打包后如果直接请求了局域网 IP 或本地服务且服务没有启动页面初始化逻辑会直接抛异常最终表现为白屏。排查思路是给渲染进程代码增加全局错误捕获把错误信息展示到页面上而不是默默地 catch 掉。5.2 生成 exe 被删除或“无法验证发布者”生成好的安装包被别人拿去双击立刻弹窗被杀毒软件处理或者 Windows 提示“无法验证发布者”。这个问题前面已经聊过根因了这里讲具体的排查顺序。第一检查文件属性里的数字签名。右键 exe查看“数字签名”选项卡如果这里显示“无”说明你的打包流程里没有正确加载证书。electron-builder 配置签名有两条路一是将证书文件放到build/目录然后设置win.certificateFile二是将证书的 base64 编码放到环境变量CSC_LINK中密码放到CSC_KEY_PASSWORD。第二种方式更适合 CI 环境不会把私钥提交到仓库。第二确认签名是否有效。signtool verify /pa your-installer.exe可以检查签名链是否完整。如果显示签名无效可能是证书过期也可能是签名脚本里漏了时间戳服务器。时间戳非常重要没有时间戳的签名在证书过期后会完全失效签名时一定要加/tr http://timestamp.digicert.com /td sha256 /fd sha256。第三如果签名没问题但杀软还是删那多半是误报。处理办法是去对应的杀毒厂商提交误报申诉在产品的“信任中心”或“白名单”里提交文件样本一般几个工作日内能解决。5.3 安装包体积从 80MB 膨胀到 200MBElectron 打包体积大是结构性的你装了一个 Chrome 内核就不可能小。但 80MB 到 200MB 这个跨度明显是配置出了问题。用electron-builder --dir先打一个目录产品然后逐层看resources\app.asar占多大如果 app.asar 本身超了 100MB多半是files配置没有过滤掉源码里的巨大目录。比如 sourcemap 文件、测试目录、.git目录都可能被打进去。resources\app.asar.unpacked占多大如果这里膨胀看看asarUnpack是不是把整个node_modules全解包了。native 模块确实需要解包但正常情况只有几十兆。locales目录占多大Electron 自带的 locale 文件有几十种语言应用如果只面向中文或英文可以把win.extraResources做筛选或者用 electron-builder 的 locale 过滤参数。还有一个隐性原因是代码里硬编码了“CDN 图片”缓存到了本地userData目录但这个跟安装包体积无关只是用户磁盘占用所以不在这里展开。如果追求极致压缩可以开启compression: maximum把 NSIS 的压缩算法调成 LZMA 最高档但代价是构建时间和安装时间显著上升。我一般默认用maximum交付体验好一点。5.4 图标双击还是默认的 Electron 图标打包后安装到桌面快捷方式图标明明对但应用运行时窗口左上角仍然是 Electron 外星人。这个在前面讲图标资产时已经提到了根因是主进程没有给BrowserWindow传 icon 参数。const mainWindow new BrowserWindow({ width: 1024, height: 768, icon: path.join(__dirname, ../build/icon.ico), // 其他配置 });配置后重启应用窗口标题栏左侧的小图标就会变成自定义图标。注意开发模式下有时显卡缓存或系统图标缓存会导致图标不刷新执行ie4uinit.exe -show清一下图标缓存或者注销再登录就能看到最新效果。还要检查任务栏里运行的图标。如果开发时固定了任务栏快捷方式它会缓存旧图标需要手动取消固定再重新固定。这不是打包问题是 Windows 的图标缓存机制在捣乱。5.5 serialport 在打包运行时直接抛异常serialport 的运行时异常基本上都集中在两类模块加载失败和串口权限不足。模块加载失败的排查路径按前面讲的原生模块三步走检查 Electron 版本和 Node ABI 是否匹配、检查asarUnpack是否把serialport相关文件解包、检查目标机器是否安装了必要驱动。手动打包目录后可以用 Node 直接测试这个.node文件是否能被当前系统加载排除安装包制作过程的问题。串口权限不足通常表现为Error: Opening COM3: Access denied。这不是代码问题是 Windows 把串口当作设备文件做了权限控制。常见场景是别的进程串口调试工具占用了该串口关掉占用进程就能解决。如果是在某些精简版 Windows 上可能还需要手动安装 USB 转串口驱动。我经常给团队的建议是在应用内增加一个“环境检测”面板启动时记录 Electron 版本、Node ABI、serialport 版本并尝试枚举串口。出错时把这段日志发给技术支持排查效率能提升一个量级。打包前建议写两个命令验证 native 模块处于可用状态后再执行打包提前发现问题。5.6 其他高频问题速查表除了上面几个大块我把平时最容易遇到的零散问题整理成一张速查表方便直接对照。现象一般原因应对方案安装包启动后没反应package.json 的 main 字段指向错误检查 main 指向打包后的文件路径打包时报ENOENT路径含中文或空格项目路径改成纯英文、无空格安装完无法写入配置安装到 Program Files 无写权限设置perMachine: false或改安装目录运行提示缺少ffmpeg.dllElectron 版本问题或杀软隔离验证杀毒软件隔离区重装应用32 位机器装了 64 位包target 未限制架构配置arch: [x64]或同时打两个架构更新后配置丢失版本号没涨或更新策略异常检查 appId 与版本号递增逻辑写在最后的几条体会Electron 在 Windows 平台打包这件事其实没有太多玄学就是把“代码签名、native 模块、NSIS 配置、路径规范”这几件事一次性做对。我见过太多团队在开发阶段把大量精力花在功能上最后打包时才发现没有买证书、没有处理 serialport、项目路径还带中文几天的工期全部耗在救火里。我个人的习惯是项目刚立项就把 electron-builder 的骨架搭好哪怕第一版功能简单也要先把安装包跑通。后续每次发版都是增量过程而不是从零开始踩一遍坑。如果你还在用 electron-packager 或者手工拷贝的方式建议花一个下午迁移到 electron-builder这个转换成本非常值得。另外如果你的项目是 Vue3 Electron 的组合麻烦记得分开看两套构建体系渲染进程的 Vite 构建和 Electron 的主进程打包互不干扰但最终在 electron-builder 的files配置里会合流。可以把渲染进程构建失效的频率降到最低观察打包目录里编译后的资源是否完整再决定是否需要排查 Vite 的 base 配置。最后一句话送给自己也送给大家Electron 打包不是项目结束前的收尾动作它应该是从第一天起就持续运行的一条流水线。坑踩得越早后面走得越稳。
返回列表