146 lines
5.1 KiB
Markdown
146 lines
5.1 KiB
Markdown
# package:mac 打包诊断报告
|
||
|
||
**诊断时间**: 2026-04-11
|
||
**项目路径**: `/Users/duanshuwen/Documents/workspace/electron/zn-ai`
|
||
**执行命令**: `pnpm run package:mac`
|
||
|
||
---
|
||
|
||
## 1. 结论摘要
|
||
|
||
**本次打包失败不是因为项目源码缺少文件或 `electron-builder.yml` 配置项缺失,而是因为**
|
||
|
||
1. **网络下载中断**:`electron-builder` 在构建 DMG 时需要下载 `dmgbuild-bundle-x86_64`,该请求被服务器中断(`ReadError: The server aborted pending request`)。
|
||
2. **并发锁竞争**:`mac.target` 同时配置了 `x64` 与 `arm64` 两种架构,`electron-builder` 并行打包时两个进程争抢 `proper-lockfile` 的缓存锁,导致下载失败后的清理阶段抛出 `Lock file is already being held` 错误。
|
||
3. **(非致命)代码签名证书已过期**:本地唯一的 `Apple Development` 证书状态为 `CSSMERR_TP_CERT_EXPIRED`,因此 `electron-builder` 跳过了正式签名,仅做了 ad-hoc 签名。这不会导致打包中断,但会影响最终 app 在 macOS Gatekeeper 下的可运行性。
|
||
|
||
---
|
||
|
||
## 2. 关键错误日志
|
||
|
||
```text
|
||
• downloading release=dmg-builder@1.2.0 file=dmgbuild-bundle-x86_64-75c8a6c.tar.gz
|
||
...
|
||
ReadError: The server aborted pending request
|
||
...
|
||
Error: Lock file is already being held
|
||
at /Users/duanshuwen/Documents/workspace/electron/zn-ai/node_modules/proper-lockfile/lib/lockfile.js:68:47
|
||
...
|
||
ELIFECYCLE Command failed with exit code 1.
|
||
```
|
||
|
||
---
|
||
|
||
## 3. 配置与文件检查结果
|
||
|
||
| 检查项 | 状态 | 说明 |
|
||
|--------|------|------|
|
||
| `package.json` | 正常 | 存在且 `package:mac` 脚本定义正确 |
|
||
| `electron-builder.yml` | 正常 | 配置完整,`mac` / `dmg` / `win` / `linux` 分平台配置齐全 |
|
||
| `resources/icons/icon.icns` | 正常 | `mac.icon` 指向的文件存在 |
|
||
| `entitlements.mac.plist` | 正常 | 文件存在并已配置 |
|
||
| `dist` / `dist-electron` | 正常 | `vite build` 阶段成功通过,产物已生成 |
|
||
| 发布产物 | 部分生成 | `zip`(x64 / arm64)已成功生成,但 DMG(x64 / arm64)因下载失败未完成 |
|
||
|
||
---
|
||
|
||
## 4. 详细原因分析
|
||
|
||
### 4.1 网络问题导致 dmg-builder 下载中断
|
||
`electron-builder` 在首次构建 DMG 时需要拉取预编译的 `dmg-builder` bundle(`dmgbuild-bundle-x86_64-75c8a6c.tar.gz`)。由于该资源托管在 GitHub / AWS CDN 上,在国内网络环境下极易出现连接被重置或请求被服务器中断的情况。
|
||
|
||
### 4.2 并发构建加剧锁竞争
|
||
`electron-builder.yml` 中配置了同时打包两种架构:
|
||
|
||
```yaml
|
||
mac:
|
||
target:
|
||
- target: dmg
|
||
arch:
|
||
- x64
|
||
- arm64
|
||
- target: zip
|
||
arch:
|
||
- x64
|
||
- arm64
|
||
```
|
||
|
||
这导致 `electron-builder` 会并行启动多个打包任务。当它们同时尝试下载/解压同一个 `dmg-builder` 缓存时,`proper-lockfile` 产生竞争;一旦其中一个下载失败,另一个在清理阶段也会因无法获取锁而报错,最终整体构建失败。
|
||
|
||
### 4.3 代码签名证书过期(仅提示,不中断构建)
|
||
日志中出现的:
|
||
|
||
```text
|
||
skipped macOS application code signing reason=cannot find valid "Developer ID Application" identity ...
|
||
"Apple Development: 562304744@qq.com (Z27TQS657B)" (CSSMERR_TP_CERT_EXPIRED)
|
||
```
|
||
|
||
这说明本地证书已过期,不会影响打包流程本身,但生成的 `.app` 没有有效的开发者签名,分发后用户打开时会遇到 "已损坏,无法打开" 的 Gatekeeper 提示。
|
||
|
||
---
|
||
|
||
## 5. 解决方案与建议
|
||
|
||
### 方案 A:分架构单独打包(推荐,最稳定)
|
||
先避免并发锁竞争,同时降低单次构建对网络的敏感度:
|
||
|
||
```bash
|
||
# 仅打包 arm64(Apple Silicon)
|
||
cd zn-ai
|
||
npx electron-builder --mac --arm64 --publish never
|
||
|
||
# 仅打包 x64(Intel)
|
||
npx electron-builder --mac --x64 --publish never
|
||
```
|
||
|
||
若网络仍不稳定,可配置代理或手动下载缓存(见方案 B)。
|
||
|
||
### 方案 B:配置 electron-builder 缓存
|
||
如果网络受限,可预先设置缓存目录并手动下载所需 bundle:
|
||
|
||
```bash
|
||
export ELECTRON_BUILDER_CACHE="$HOME/.electron-builder-cache"
|
||
```
|
||
|
||
然后手动将 `dmgbuild-bundle-x86_64-75c8a6c.tar.gz` 放置到缓存目录的 `cache/dmg-builder` 子目录下,再执行打包。
|
||
|
||
### 方案 C:修改 `electron-builder.yml` 降低并发
|
||
在 `mac.target` 里先只保留当前常用架构(如 `arm64`),需要时再切换:
|
||
|
||
```yaml
|
||
mac:
|
||
target:
|
||
- target: dmg
|
||
arch:
|
||
- arm64
|
||
- target: zip
|
||
arch:
|
||
- arm64
|
||
```
|
||
|
||
### 方案 D:修复代码签名(分发前必须)
|
||
若计划将应用分发给其他用户,需要:
|
||
1. 在 Apple Developer 后台续期或重新申请 **Developer ID Application** 证书;
|
||
2. 将 `notarize` 改为 `true` 并配置正确的 `teamId`;
|
||
3. 在构建机器上安装新证书后重新打包。
|
||
|
||
---
|
||
|
||
## 6. 附录:构建产物现状
|
||
|
||
截至诊断时,`release/` 目录下已生成:
|
||
|
||
- `NIANXX-1.0.0-mac-x64.zip` (133 MB)
|
||
- `NIANXX-1.0.0-mac-arm64.zip` (129 MB)
|
||
- 对应的 `.blockmap` 文件
|
||
|
||
**未生成**:
|
||
- `NIANXX-1.0.0-mac-x64.dmg`
|
||
- `NIANXX-1.0.0-mac-arm64.dmg`
|
||
|
||
原因即上述网络下载中断 + 并发锁竞争。
|
||
|
||
---
|
||
|
||
*报告结束*
|