正确生成时应该长什么样(Windows x64)
当你跑 pnpm build:win:x64 成功后,项目根目录下通常会出现(以你仓库配置为准):
-
dist/-
dist/win-unpacked/:解包后的可运行目录(开发者最常用来验证)
-
注会帮.exe
resources/-
app.asar(核心打包产物:你的 JS/CSS/资源被打成一个 asar 包) -
app.asar.unpacked/(放"不能进 asar"的东西,比如原生.node、部分资源) -
...(electron 运行时依赖)
-
-
dist/注会帮-1.7.21-x64-setup.exe:NSIS 安装包(artifactName 里配置的) -(如果你还配置了 portable)dist/注会帮-1.7.21-x64-portable.exe -
dist/builder-effective-config.yaml:electron-builder 合并后的"最终生效配置"(用于排查问题)
-
win-unpacked 是"安装包的原料",setup/portable 是"最终交付物"。
pnpm build:win:x64 的含义
看你的 package.json:
build:win:x64=dotenv npm run build && electron-builder --win --x64
拆开就是两段:
-
npm run build在你这里是:npm run typecheck && electron-vite build-
typecheck:用tsgo对 Node/Web 两套 tsconfig 做类型检查 -
electron-vite build:把 main/renderer/preload 编译到out/(产物是可供 Electron 运行的 JS/CSS 等)
-
-
electron-builder --win --x64-
把 Electron 运行时 + 你的编译产物 + 依赖,按
electron-builder.yml打包 -
生成
win-unpacked,再基于它生成安装包/便携包等
-
dist 和 build 文件夹分别是什么
dist/(输出目录)
electron-builder 的输出目录(打包产物与中间产物),例如:
-
dist/win-unpacked/(解包目录) -
dist/*setup.exe(安装包) -
dist/builder-effective-config.yaml(生效配置)
你终端报的 "
dist\win-unpacked\resources\app.asar被占用删不掉" 就是它在重建dist时清理失败。
build/(打包资源目录)
在你的 electron-builder.yml 里配置了:
directories.buildResources: build
所以 build/ 放的是 打包用资源,比如:
-
build/icon.png(应用图标) -
build/nsis-installer.nsh(NSIS 安装器脚本) -
build/entitlements.mac.plist(mac 相关权限文件)
它通常不是产物,而是打包输入。
打包原理(把它当成"组装一台可分发的 Electron 应用")
Electron 应用要能在用户电脑上跑,至少需要三类东西:
-
Electron 运行时:相当于"自带的 Chromium + Node"
-
你的应用代码:main/renderer/preload 编译后的 JS/CSS/静态资源
-
Node 依赖:尤其是原生模块(
.node)要匹配 Electron 版本/架构
electron-builder 做的事就是:
-
收集文件:根据
electron-builder.yml的files白名单/黑名单,把该带的带上、不该带的剔除 -
打 asar:把应用资源打成
resources/app.asar(启动更快、文件更少) -
处理原生模块
:
-
跑
@electron/rebuild,确保.node与electronVersion、arch匹配 -
把某些必须"裸文件存在"的东西放到
app.asar.unpacked/
-
-
生成解包目录:
dist/win-unpacked/(可直接运行) -
再封装成发行物:NSIS 安装包(setup.exe)、portable 等
-
(可选)代码签名:调用
signtool对 exe/dll 等签名
构建命令运行时发生了什么?(按你终端日志对应解释)
你贴的那段输出,基本是 electron-builder 阶段,常见关键行含义如下:
-
built in 18.55s通常指前面的编译(vite/rollup)完成用时(不同版本输出略有差异)。 -
electron-builder version=... loaded configuration file=electron-builder.yml开始打包,并读取你的配置。 -
writing effective config file=dist\builder-effective-config.yaml把"最终合并生效"的配置写出来(非常重要的排错依据)。 -
Skipping install: target (win32/x64) matches current system你的scripts/before-pack.js里有逻辑:目标平台架构和当前一致就不额外pnpm install(避免为了别的平台装依赖)。 -
executing @electron/rebuild ... electronVersion=40.6.1 arch=x64重建原生依赖,让它们能在 Electron 40.6.1、x64 下运行。 -
packaging platform=win32 arch=x64 ... appOutDir=dist\win-unpacked开始组装win-unpacked目录。 -
remove ... app.asar: The process cannot access the file because it is being used by another process.关键报错:builder 要清空旧目录/旧 asar,但文件被占用(通常是你正在运行win-unpacked里的 exe,或杀软扫描/资源管理器预览锁定)。 -
app-builder.exe process failed ERR_ELECTRON_BUILDER_CANNOT_EXECUTEelectron-builder 内部的打包工具(Go 写的 app-builder)因为上一步失败而退出。
方法论:你该如何"掌控"构建与打包
-
区分两个世界
-
pnpm build:主要解决"能不能编译、类型对不对" -
pnpm build:win:x64:在pnpm build的基础上,再解决"能不能打包分发"
-
-
排错优先级
-
先让
pnpm build稳定通过(类型 + 编译) -
再处理 electron-builder(原生模块、文件过滤、asar、签名、安装包)
-
-
遇到 Windows "文件占用"类错误的固定套路
-
不要运行
dist/win-unpacked里的 exe 同时打包 -
清理
dist/后重试 -
必要时把
dist加 Defender 排除项
-