# 构建与部署

<cite>
**本文引用的文件**
- [package.json](file://package.json)
- [next.config.ts](file://next.config.ts)
- [electron-builder.json](file://electron-builder.json)
- [scripts/build-electron.mjs](file://scripts/build-electron.mjs)
- [scripts/after-sign.js](file://scripts/after-sign.js)
- [electron/main.ts](file://electron/main.ts)
- [electron/preload.ts](file://electron/preload.ts)
- [README.md](file://README.md)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本指南面向Forge项目的构建与部署，覆盖以下关键主题：
- Next.js构建与Electron打包的完整流程
- cross-env环境变量与构建脚本的工作机制
- 跨平台打包配置（Windows、macOS、Linux）
- electron-builder配置详解与自定义参数
- 发布流程（版本管理、签名、分发）
- CI/CD集成与自动化部署建议
- 常见问题与优化技巧

## 项目结构
Forge采用“Next.js前端 + Electron桌面壳”的混合架构。生产构建时，Next.js以standalone模式输出，Electron主进程与预加载脚本通过esbuild打包，最终由electron-builder进行跨平台打包。

```mermaid
graph TB
subgraph "构建阶段"
A["Next.js 构建<br/>standalone 输出"] --> B["Electron 打包<br/>esbuild + scripts/build-electron.mjs"]
C["脚本与配置<br/>package.json + next.config.ts + electron-builder.json"] --> B
end
subgraph "打包阶段"
B --> D["electron-builder<br/>跨平台打包"]
D --> E["macOS DMG / 目录"]
D --> F["Windows NSIS 安装包"]
D --> G["Linux AppImage"]
end
```

图表来源
- [package.json:13-26](file://package.json#L13-L26)
- [next.config.ts:3-10](file://next.config.ts#L3-L10)
- [electron-builder.json:5-55](file://electron-builder.json#L5-L55)
- [scripts/build-electron.mjs:1-399](file://scripts/build-electron.mjs#L1-L399)

章节来源
- [package.json:13-26](file://package.json#L13-L26)
- [next.config.ts:3-10](file://next.config.ts#L3-L10)
- [electron-builder.json:5-55](file://electron-builder.json#L5-L55)

## 核心组件
- Next.js构建配置：启用standalone输出、禁用压缩、外置特定包，确保Electron环境下的本地运行与打包稳定性。
- Electron构建脚本：统一使用esbuild构建主进程与预加载脚本；在打包前处理符号链接、修复pnpm hoisting、剥离开发机路径、清理敏感目录、复制模板与静态资源、下载并打包Node运行时、重建原生模块。
- electron-builder配置：定义产物目录、文件包含/排除、额外资源、签名钩子、平台目标与安装器参数、安全策略（macOS硬加固、沙箱继承、暗色模式支持）。
- 签名后置脚本：macOS下根据环境变量决定是否使用开发者ID证书或进行ad-hoc签名，并对框架、辅助应用与二进制进行逐层签名与验证。
- Electron主进程：在生产环境中使用打包好的Node运行时启动Next.js standalone server，扩展PATH以兼容CLI工具，监听端口并创建窗口；开发模式则直接访问本地Next.js开发服务器。

章节来源
- [next.config.ts:3-10](file://next.config.ts#L3-L10)
- [scripts/build-electron.mjs:17-32](file://scripts/build-electron.mjs#L17-L32)
- [electron-builder.json:56-124](file://electron-builder.json#L56-L124)
- [scripts/after-sign.js:5-82](file://scripts/after-sign.js#L5-L82)
- [electron/main.ts:74-139](file://electron/main.ts#L74-L139)

## 架构总览
下图展示了从开发到发布的整体流程，以及各组件之间的交互关系。

```mermaid
sequenceDiagram
participant Dev as "开发者"
participant N as "Next.js 构建"
participant E as "Electron 构建脚本"
participant EB as "electron-builder"
participant OS as "操作系统/平台"
Dev->>N : 运行构建脚本
N-->>Dev : 生成 .next/standalone
Dev->>E : 执行 Electron 打包脚本
E-->>Dev : 产出 dist-electron 与修正后的 standalone
Dev->>EB : 触发打包指定平台
EB->>OS : 生成 DMG/AppImage/NSIS
OS-->>Dev : 可分发的应用包
```

图表来源
- [package.json:18-25](file://package.json#L18-L25)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)
- [electron-builder.json:62-124](file://electron-builder.json#L62-L124)

## 详细组件分析

### Next.js 构建与打包
- standalone输出：确保打包后的服务可独立运行，便于Electron通过子进程启动。
- 禁用压缩与图片优化：避免SSE流被压缩破坏，同时减少构建时间。
- 外置包：将某些依赖标记为外部包，避免webpack打包导致的原生行为变化。

```mermaid
flowchart TD
Start(["开始：Next.js 构建"]) --> Out["输出 standalone 目录"]
Out --> Ext["@larksuiteoapi/node-sdk 外置"]
Ext --> End(["结束"])
```

图表来源
- [next.config.ts:3-10](file://next.config.ts#L3-L10)

章节来源
- [next.config.ts:3-10](file://next.config.ts#L3-L10)

### Electron 打包脚本（scripts/build-electron.mjs）
该脚本负责在electron-builder打包前，对Next.js standalone产物与Electron源码进行一系列准备与修正，确保最终产物稳定可靠。

```mermaid
flowchart TD
S(["入口：构建 Electron + Standalone 准备"]) --> B1["步骤1：esbuild 构建 main + preload"]
B1 --> B2["步骤2：解析 .next/standalone 中的符号链接"]
B2 --> B3["步骤3：复制 templates/ 到 standalone"]
B3 --> B4["步骤4：修复 pnpm hoisting 间隙"]
B4 --> B5["步骤5：剥离开发机绝对路径"]
B5 --> B6["步骤6：清理 .forge-data隐私"]
B6 --> B7["步骤7：复制 public/ 与 .next 静态资源"]
B7 --> B8["步骤8：下载并打包 Node 运行时"]
B8 --> B9["步骤9：重建原生模块如 better-sqlite3"]
B9 --> E(["结束"])
```

图表来源
- [scripts/build-electron.mjs:6-32](file://scripts/build-electron.mjs#L6-L32)
- [scripts/build-electron.mjs:34-73](file://scripts/build-electron.mjs#L34-L73)
- [scripts/build-electron.mjs:75-86](file://scripts/build-electron.mjs#L75-L86)
- [scripts/build-electron.mjs:88-155](file://scripts/build-electron.mjs#L88-L155)
- [scripts/build-electron.mjs:157-202](file://scripts/build-electron.mjs#L157-L202)
- [scripts/build-electron.mjs:204-212](file://scripts/build-electron.mjs#L204-L212)
- [scripts/build-electron.mjs:214-292](file://scripts/build-electron.mjs#L214-L292)
- [scripts/build-electron.mjs:294-336](file://scripts/build-electron.mjs#L294-L336)

章节来源
- [scripts/build-electron.mjs:6-32](file://scripts/build-electron.mjs#L6-L32)
- [scripts/build-electron.mjs:34-73](file://scripts/build-electron.mjs#L34-L73)
- [scripts/build-electron.mjs:75-86](file://scripts/build-electron.mjs#L75-L86)
- [scripts/build-electron.mjs:88-155](file://scripts/build-electron.mjs#L88-L155)
- [scripts/build-electron.mjs:157-202](file://scripts/build-electron.mjs#L157-L202)
- [scripts/build-electron.mjs:204-212](file://scripts/build-electron.mjs#L204-L212)
- [scripts/build-electron.mjs:214-292](file://scripts/build-electron.mjs#L214-L292)
- [scripts/build-electron.mjs:294-336](file://scripts/build-electron.mjs#L294-L336)

### electron-builder 配置与跨平台打包
- 产物与资源：定义输出目录、文件包含/排除、额外资源（standalone、public、templates、node-runtime）。
- 安全与签名：macOS启用hardened runtime、暗色模式、entitlements与inherit；配置afterSign钩子；Windows使用NSIS安装器；Linux生成AppImage。
- 平台目标：macOS仅arm64 dmg/dir；Windows x64 nsis；Linux x64 AppImage。

```mermaid
graph TB
CFG["electron-builder.json"] --> OUT["输出目录 release/"]
CFG --> FILES["files 包含/排除规则"]
CFG --> RES["extraResources 额外资源"]
CFG --> MAC["macOS 配置"]
CFG --> WIN["Windows 配置"]
CFG --> LNX["Linux 配置"]
MAC --> SIGN["签名钩子 afterSign"]
```

图表来源
- [electron-builder.json:5-18](file://electron-builder.json#L5-L18)
- [electron-builder.json:19-55](file://electron-builder.json#L19-L55)
- [electron-builder.json:62-98](file://electron-builder.json#L62-L98)
- [electron-builder.json:99-114](file://electron-builder.json#L99-L114)
- [electron-builder.json:115-124](file://electron-builder.json#L115-L124)

章节来源
- [electron-builder.json:5-18](file://electron-builder.json#L5-L18)
- [electron-builder.json:19-55](file://electron-builder.json#L19-L55)
- [electron-builder.json:62-98](file://electron-builder.json#L62-L98)
- [electron-builder.json:99-114](file://electron-builder.json#L99-L114)
- [electron-builder.json:115-124](file://electron-builder.json#L115-L124)

### 签名后置脚本（macOS）
该脚本在electron-builder完成后执行，用于验证或应用签名，确保应用可被Gatekeeper接受。

```mermaid
sequenceDiagram
participant EB as "electron-builder"
participant AS as "after-sign.js"
participant CS as "codesign 工具"
EB->>AS : 触发 afterSign 钩子
AS->>AS : 检测是否为 macOS 平台
AS->>AS : 检测开发者ID证书/CSC_* 环境变量
AS->>CS : 验证签名如有
AS->>CS : 对 .node/.dylib/.so 签名
AS->>CS : 对 Frameworks 与 Helper App 签名
AS->>CS : 对主应用签名
AS->>CS : 最终验证签名
```

图表来源
- [scripts/after-sign.js:5-82](file://scripts/after-sign.js#L5-L82)

章节来源
- [scripts/after-sign.js:5-82](file://scripts/after-sign.js#L5-L82)

### Electron 主进程与预加载桥接
- 主进程：在生产模式下使用打包的Node运行时启动standalone server，扩展PATH以识别CLI工具，监听端口并创建窗口；开发模式直接访问本地开发服务器。
- 预加载：通过contextBridge暴露安全API，供渲染进程调用文件系统、剪贴板、数据目录等能力。

```mermaid
sequenceDiagram
participant App as "Electron App"
participant Main as "main.ts"
participant Preload as "preload.ts"
participant Node as "Node 运行时"
participant Win as "BrowserWindow"
App->>Main : 应用就绪
Main->>Main : 解析 Node 路径生产/开发
Main->>Node : 启动 standalone serverspawn
Node-->>Main : 服务就绪端口
Main->>Win : 创建窗口并加载 URL
Preload-->>Win : 注入安全 APIcontextBridge
```

图表来源
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)

章节来源
- [electron/main.ts:177-289](file://electron/main.ts#L177-L289)
- [electron/preload.ts:5-23](file://electron/preload.ts#L5-L23)

## 依赖关系分析
- 构建脚本依赖：Next.js构建产物（standalone）、Electron源码（main.ts、preload.ts）、electron-builder配置。
- 运行时依赖：生产模式下使用打包的Node运行时；开发模式使用系统Node。
- 平台差异：Windows使用nsis安装器；macOS使用dmg/dir并启用hardened runtime；Linux使用AppImage。

```mermaid
graph LR
P["package.json 脚本"] --> N["next.config.ts"]
P --> E["scripts/build-electron.mjs"]
E --> EB["electron-builder.json"]
EB --> M["macOS"]
EB --> W["Windows"]
EB --> L["Linux"]
```

图表来源
- [package.json:13-26](file://package.json#L13-L26)
- [next.config.ts:3-10](file://next.config.ts#L3-L10)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)
- [electron-builder.json:62-124](file://electron-builder.json#L62-L124)

章节来源
- [package.json:13-26](file://package.json#L13-L26)
- [next.config.ts:3-10](file://next.config.ts#L3-L10)
- [scripts/build-electron.mjs:381-399](file://scripts/build-electron.mjs#L381-L399)
- [electron-builder.json:62-124](file://electron-builder.json#L62-L124)

## 性能考量
- Next.js压缩关闭：避免SSE流被gzip破坏，提升实时通信体验。
- esbuild构建：Electron主进程与预加载脚本使用esbuild，构建速度快、体积小。
- standalone模式：减少运行时依赖，提高启动速度与可移植性。
- 原生模块重建：针对打包的Node版本重建better-sqlite3，避免ABI不匹配导致的崩溃。
- 资源精简：移除不必要的node_modules子目录与系统文件，缩小包体。

章节来源
- [next.config.ts:5](file://next.config.ts#L5)
- [scripts/build-electron.mjs:17-32](file://scripts/build-electron.mjs#L17-L32)
- [scripts/build-electron.mjs:214-292](file://scripts/build-electron.mjs#L214-L292)
- [scripts/build-electron.mjs:294-336](file://scripts/build-electron.mjs#L294-L336)

## 故障排查指南
- 无法找到claude命令
  - 现象：应用启动时报错提示找不到claude命令。
  - 处理：安装并登录Claude Code CLI，确认命令可用后再启动应用。
  - 参考：[README.md:298-305](file://README.md#L298-L305)

- macOS首次启动弹窗/无法打开
  - 现象：首次启动出现Gatekeeper警告或无法打开。
  - 处理：参考系统设置中的“隐私与安全性”进行允许，或使用xattr清除属性后重试。
  - 参考：[README.md:278-291](file://README.md#L278-L291)

- 服务器启动失败（生产模式）
  - 现象：Electron启动standalone server失败。
  - 排查：检查打包的Node运行时是否存在、端口占用、PATH扩展是否正确。
  - 参考：[electron/main.ts:74-139](file://electron/main.ts#L74-L139)

- 原生模块ABI不匹配
  - 现象：better-sqlite3在打包后无法加载。
  - 处理：确保已为打包的Node版本重建原生模块，或使用预编译版本。
  - 参考：[scripts/build-electron.mjs:294-336](file://scripts/build-electron.mjs#L294-L336)

- 符号链接导致打包失败
  - 现象：electron-builder无法正确打包符号链接。
  - 处理：脚本会自动解析符号链接为真实文件，若仍有问题，请检查standalone目录结构。
  - 参考：[scripts/build-electron.mjs:34-73](file://scripts/build-electron.mjs#L34-L73)

- macOS签名问题
  - 现象：应用无法通过Gatekeeper校验。
  - 处理：配置CSC_LINK或CSC_NAME环境变量使用开发者ID证书；否则脚本会进行ad-hoc签名并验证。
  - 参考：[scripts/after-sign.js:18-42](file://scripts/after-sign.js#L18-L42)

章节来源
- [README.md:278-291](file://README.md#L278-L291)
- [README.md:298-305](file://README.md#L298-L305)
- [electron/main.ts:74-139](file://electron/main.ts#L74-L139)
- [scripts/build-electron.mjs:294-336](file://scripts/build-electron.mjs#L294-L336)
- [scripts/build-electron.mjs:34-73](file://scripts/build-electron.mjs#L34-L73)
- [scripts/after-sign.js:18-42](file://scripts/after-sign.js#L18-L42)

## 结论
Forge的构建与部署流程围绕“Next.js standalone + Electron + electron-builder”展开，通过脚本在打包前完成符号链接解析、pnpm hoisting修复、路径剥离、Node运行时打包与原生模块重建，确保跨平台产物的稳定性与可移植性。配合macOS hardened runtime与签名钩子，满足现代平台的安全要求。结合CI/CD自动化，可实现高效、可靠的持续交付。

## 附录

### 构建与打包命令
- 开发模式：同时启动Next.js开发服务器与Electron主进程。
- 生产构建：先构建Next.js，再执行Electron打包脚本。
- 跨平台打包：分别针对macOS、Windows、Linux生成对应安装包。

章节来源
- [package.json:13-26](file://package.json#L13-L26)

### 环境变量与签名配置
- macOS签名：可通过CSC_LINK或CSC_NAME环境变量提供开发者ID证书；否则使用ad-hoc签名。
- 签名钩子：afterSign在electron-builder完成后执行，按层级对应用进行签名与验证。

章节来源
- [scripts/after-sign.js:18-42](file://scripts/after-sign.js#L18-L42)
- [electron-builder.json:57](file://electron-builder.json#L57)

### CI/CD 集成建议
- macOS签名：在CI中配置CSC_LINK或CSC_NAME，并确保构建机具备相应证书与权限。
- Windows签名：配置代码签名证书与密码，使用electron-builder的sign配置。
- Linux打包：在Linux runner中执行打包命令，生成AppImage。
- 缓存策略：缓存node_modules与.pnpm-store，加速构建。
- 自动发布：在发布分支触发构建与上传，使用GitHub Releases或内部制品库。

[本节为通用实践建议，不直接分析具体文件，故无章节来源]