# ClawX 项目编译打包实现思路 ## 项目概述 ClawX 是一个基于 Electron 的图形化 AI 助手应用,核心功能依赖于 OpenClaw 网关。项目采用现代前端技术栈: - **前端框架**: React + TypeScript - **构建工具**: Vite - **包管理器**: pnpm(使用工作区与虚拟存储) - **桌面框架**: Electron - **打包工具**: electron-builder 项目结构遵循标准 Electron 应用布局: - `electron/main/` – 主进程代码 - `electron/preload/` – 预加载脚本 - `electron/gateway/` – 网关通信层 - `src/` – 渲染进程(React 应用) - `resources/` – 静态资源(图标、 CLI 工具、预置技能) - `scripts/` – 构建与打包辅助脚本 - `dist/` – Vite 构建输出(渲染进程) - `dist-electron/` – Electron 主进程与预加载脚本构建输出 ## 核心构建流程 ### 1. 开发构建 (`pnpm run dev`) - 使用 Vite 开发服务器启动渲染进程热重载 - `vite-plugin-electron` 自动编译主进程与预加载脚本,并启动 Electron ### 2. 生产构建 (`pnpm run build`) 完整构建命令依次执行以下步骤: ```bash vite build && zx scripts/bundle-openclaw.mjs && zx scripts/bundle-openclaw-plugins.mjs && zx scripts/bundle-preinstalled-skills.mjs && electron-builder ``` #### 2.1 渲染进程构建 (`vite build`) - 基于 `vite.config.ts` 配置 - 使用 `@vitejs/plugin-react` 处理 React - 输出目录: `dist/` - 关键配置: - `base: './'` – 确保 Electron 文件协议下资源路径正确 - 别名映射:`@` → `src/`,`@electron` → `electron/` #### 2.2 主进程与预加载脚本构建 (`vite-plugin-electron`) - 配置在 `vite.config.ts` 的 `electron()` 插件中 - 两个入口: - `electron/main/index.ts` → 输出到 `dist-electron/main/` - `electron/preload/index.ts` → 输出到 `dist-electron/preload/` - 主进程构建使用自定义 `external` 规则,排除 Node.js 内置模块和绝对路径模块 #### 2.3 OpenClaw 核心包打包 (`scripts/bundle-openclaw.mjs`) **核心挑战**:pnpm 虚拟存储导致依赖分散,直接复制 `node_modules/openclaw` 会丢失运行时依赖。 **解决方案**:广度优先遍历 pnpm 虚拟存储,收集所有传递依赖。 **步骤**: 1. 解析 `node_modules/openclaw` 的真实路径(跟随 pnpm 符号链接) 2. 确定 openclaw 所在的虚拟存储 `node_modules` 目录(例如 `.pnpm/openclaw@版本/node_modules/`) 3. BFS 遍历: - 扫描虚拟存储 `node_modules` 下的所有包(排除 `.bin`) - 对每个包解析真实路径,记录包名与路径 - 找到该包自身的虚拟存储 `node_modules`,继续遍历其依赖 4. 跳过开发依赖(如 `typescript`、`@playwright/test`)和特定作用域包(如 `@types/`) 5. 将收集到的所有包复制到 `build/openclaw/node_modules/`(扁平化结构) 6. 去重处理:相同包名只保留首次遇到的版本(避免版本冲突) 7. 清理:移除开发文档、测试目录、源码映射、类型定义等无用文件 8. 修补已知问题模块: - `node-domexception` – 修复 CJS 导出为 undefined 的问题 - `lru-cache` – 添加 `LRUCache` 命名导出,解决 Node.js 22+ ESM 互操作问题 - 运行时 spawn 调用 – 添加 `windowsHide: true` 避免 Windows 控制台窗口闪烁 #### 2.4 插件打包 (`scripts/bundle-openclaw-plugins.mjs`) - 打包第三方 OpenClaw 插件:钉钉、企业微信、飞书、微信 - 使用类似的 BFS 算法收集插件及其传递依赖 - 输出到 `build/openclaw-plugins/` 各插件目录 #### 2.5 预置技能打包 (`scripts/bundle-preinstalled-skills.mjs`) - 将 `resources/skills/` 下的预置技能打包到 `build/preinstalled-skills/` - 确保技能配置文件(`SKILL.md`)与依赖完整 #### 2.6 Electron 应用打包 (`electron-builder`) - 配置文件:`electron-builder.yml` - 输入文件: - `dist/` – 渲染进程构建结果 - `dist-electron/` – 主进程与预加载脚本 - `package.json` – 应用元数据 - 额外资源(`extraResources`): - `resources/` – 静态资源(排除图标源文件、截图等) - `build/openclaw/` – 打包后的 OpenClaw 核心 - `build/preinstalled-skills/` – 预置技能包 - **关键问题**:`electron-builder` 遵循 `.gitignore` 规则,会跳过 `node_modules/` 目录,导致 `build/openclaw/node_modules/` 无法被复制。 **解决方案**:在 `afterPack` 钩子(`scripts/after-pack.cjs`)中手动复制。 ### 3. 平台特定打包命令 - `package:mac` – 仅构建 macOS 安装包(DMG/ZIP) - `package:win` – 构建 Windows 安装包(NSIS),预先下载 Windows 平台所需的 UV 和 Node.js 二进制文件 - `package:linux` – 构建 Linux 安装包(AppImage/DEB/RPM) ## 依赖管理与打包优化 ### pnpm 虚拟存储适配 - pnpm 使用内容寻址存储,依赖通过符号链接组织 - 构建脚本必须解析真实路径,遍历虚拟存储以收集完整依赖树 - 支持 Windows 长路径(前缀 `\\?\` 绕过 260 字符限制) ### 体积优化 1. **开发文件移除**:删除 `.d.ts`、`.map`、测试目录、文档等 2. **平台特定裁剪**: - `koffi` 本地库:只保留目标平台架构的预构建二进制文件 - 作用域本地包(如 `@napi-rs/canvas-*`、`@img/sharp-*`):移除非目标平台变体 3. **大文件移除**:删除 `node-llama-cpp/llama`、`pdfjs-dist/legacy` 等非必需大目录 ### 兼容性修补 1. **CJS/ESM 互操作**: - `lru-cache` 旧版本缺少命名导出,通过追加 `exports.LRUCache` 补丁解决 - `https-proxy-agent` 补充 `require` 导出条件,避免循环依赖错误 2. **Windows 控制台隐藏**:修补 spawn 调用,添加 `windowsHide: true` 选项 3. **插件 ID 修正**:某些插件编译后硬编码的 ID 与声明不一致,在打包后修正 ## 安装包生成与分发 ### 多平台配置 - **macOS**: - 目标格式:DMG、ZIP - 启用强运行时(`hardenedRuntime`)与公证(`notarize`) - 自定义 DMG 背景与窗口布局 - **Windows**: - 目标格式:NSIS 安装程序 - 禁用更新签名验证(使用 OSS 分发) - 优化安装速度:修补 NSIS 脚本,直接解压到安装目录,避免 Defender 扫描导致的缓慢文件复制 - **Linux**: - 目标格式:AppImage、DEB、RPM - 适配 Ubuntu 24.04 t64 ABI 过渡(使用 `|` 语法声明备选包名) ### 自动更新 - 主分发渠道:阿里云 OSS(国内用户速度优先) - 备用渠道:GitHub Releases - 使用 `electron-updater` 实现后台更新 ## 构建脚本角色概览 | 脚本文件 | 功能描述 | |----------|----------| | `bundle-openclaw.mjs` | 打包 OpenClaw 核心及其所有传递依赖 | | `bundle-openclaw-plugins.mjs` | 打包第三方插件(钉钉、企业微信等) | | `bundle-preinstalled-skills.mjs` | 打包预置技能包 | | `after-pack.cjs` | `electron-builder` 后处理钩子,负责:
• 复制被忽略的 `node_modules`
• 平台特定文件清理
• 模块兼容性修补
• Windows NSIS 脚本优化 | | `download-bundled-uv.mjs` | 下载平台特定的 UV 二进制(Python 包管理器) | | `download-bundled-node.mjs` | 下载平台特定的 Node.js 运行时 | | `generate-icons.mjs` | 生成各平台所需图标格式 | ## 关键配置要点 ### `electron-builder.yml` 要点 - `extraResources` 复制资源,但需注意 `.gitignore` 排除问题 - `asar: true` 打包为归档,但解压 `*.node` 原生模块和 `lru-cache` 以便修补 - `npmRebuild: false` 禁止重建原生模块(所有原生模块属于 OpenClaw,在独立进程中运行) - 发布配置支持 OSS 与 GitHub 双渠道 ### `vite.config.ts` 要点 - 使用 `vite-plugin-electron` 一体化构建主进程与预加载脚本 - 主进程外部化规则确保 Node.js 内置模块不打包 - 路径别名简化导入 ## 总结 ClawX 的构建打包流程体现了对现代 Electron 应用复杂依赖管理的深刻理解,主要特点包括: 1. **深度 pnpm 集成**:专门处理虚拟存储的依赖收集,确保运行时完整性。 2. **分层打包**:将 OpenClaw 核心、插件、技能分别打包,模块清晰。 3. **跨平台优化**:针对各平台特性进行资源裁剪、性能优化与体验改进。 4. **兼容性保障**:主动修补第三方模块的 CJS/ESM 互操作问题,确保 Electron 40+(Node.js 22+)稳定运行。 5. **构建效率**:通过 BFS 依赖收集、开发文件清理、Windows 安装过程优化等手段,控制包体积与构建时间。 此流程确保了 ClawX 能够在三大桌面平台提供一致、稳定、高效的 AI 助手体验。 # zn-ai 项目打包编译重构计划 ## 项目现状分析 zn-ai 项目当前使用以下技术栈: - **前端框架**: Vue 3 + TypeScript - **构建工具**: Vite(分拆配置:`vite.main.config.ts`、`vite.renderer.config.ts`、`vite.preload.config.ts`) - **包管理器**: npm(检测到 `package-lock.json`) - **桌面框架**: Electron 38.2.2 - **打包工具**: electron-forge + @electron-forge/plugin-vite - **代码保护**: bytenode 字节码编译(通过自定义 `vite-plugin-electron-encrypt` 插件实现) 当前构建流程: 1. 开发构建:`npm start`(使用 electron-forge start) 2. 生产构建:`npm run package`、`npm run make`、`npm run build:encrypt` 3. 自定义脚本:`clean.js`、`generateProdEntry.js` 用于清理和生成字节码入口 ## 重构目标 将 ClawX 项目的现代化构建打包思路应用于 zn-ai 项目,主要目标: 1. **统一构建配置**:使用单个 `vite.config.ts` 替代多个 Vite 配置文件 2. **迁移打包工具**:从 electron-forge 迁移到 electron-builder 3. **优化构建流程**:采用模块化构建脚本,提高可维护性 4. **保持代码保护**:保留或改进 bytenode 字节码保护机制 5. **提升跨平台体验**:借鉴 ClawX 的平台特定优化策略 ## 可行性评估 ### 可行方面 1. **技术栈兼容性**:Vite + Electron 组合在两个项目中都得到验证 2. **配置迁移**:Vite 配置可以合并,别名映射可以统一 3. **打包工具迁移**:electron-builder 功能覆盖 electron-forge,且配置更简洁 4. **脚本模块化**:ClawX 的脚本设计可以作为参考 ### 挑战与风险 1. **bytenode 集成**:ClawX 未使用字节码保护,需要设计新的集成方案 2. **依赖管理差异**:zn-ai 使用 npm,ClawX 使用 pnpm 虚拟存储,依赖收集策略可能不同 3. **目录结构调整**:需要适应新的输出目录结构(`dist/`、`dist-electron/`) 4. **现有功能兼容性**:确保所有现有功能在重构后正常工作 ## 详细实施步骤 ### 第一阶段:基础配置迁移(预计 2-3 天) #### 1.1 更新依赖项 - 移除 `@electron-forge` 相关依赖 - 添加 `electron-builder`、`vite-plugin-electron`、`vite-plugin-electron-renderer` - 更新 `electron` 版本到与 ClawX 兼容的版本(当前 40.6.0) - 检查其他依赖兼容性 #### 1.2 创建统一的 Vite 配置 - 创建 `vite.config.ts`,整合现有三个配置文件的设置 - 配置 `vite-plugin-electron` 插件,处理主进程和预加载脚本 - 配置 `vite-plugin-electron-renderer` 插件 - 统一别名映射,保持现有别名兼容性 - 保留 Vue 相关插件配置(`@vitejs/plugin-vue`、`unplugin-auto-import`、`@tailwindcss/vite`) #### 1.3 配置 electron-builder - 创建 `electron-builder.yml` 配置文件 - 基于 zn-ai 需求定制: - 应用 ID、产品名称、版权信息 - 输出目录配置 - 文件包含规则(`dist/`、`dist-electron/`、`package.json`) - 额外资源(`public/`、`src/main/scripts/` 等) - 平台特定配置(Windows、macOS、Linux) #### 1.4 更新 package.json 脚本 - 更新 `scripts` 部分: - `dev`: 使用 Vite 开发服务器 + electron 插件 - `build`: 生产构建流程 - `package`: 仅打包应用,不生成安装包 - `package:win`、`package:mac`、`package:linux`: 平台特定打包 - `release`: 发布版本 - 移除不再需要的脚本(`generate-prod-entry`、`clean` 等) ### 第二阶段:bytenode 保护机制重构(预计 1-2 天) #### 2.1 分析现有保护机制 - 当前机制:通过 `vite-plugin-electron-encrypt` 插件在主进程构建后调用 bytenode 编译 - 输出:`.jsc` 字节码文件,并生成新的入口文件 #### 2.2 设计新的集成方案 **方案 A:保留现有插件,适配新构建流程** - 修改 `vite-plugin-electron-encrypt` 插件,使其与 `vite-plugin-electron` 协同工作 - 在 `vite-plugin-electron` 的 `onstart` 或构建完成后钩子中集成字节码编译 **推荐方案**:方案 A,因为字节码编译应在主进程构建完成后立即进行,而不是在打包后。 #### 2.3 实现保护机制 - 创建新的插件或修改现有插件 - 确保开发模式下不进行字节码编译(保持源码可调试) - 生产构建时自动编译并替换入口 ### 第三阶段:构建脚本优化(预计 1-2 天) #### 3.1 分析 zn-ai 的特殊需求 - 检查是否有类似 ClawX 的复杂依赖收集需求 - 分析 `src/main/scripts/` 目录的处理需求 - 检查是否需要平台特定的二进制文件 #### 3.2 创建必要的构建脚本 - 如果需要依赖收集,参考 ClawX 的 `bundle-openclaw.mjs` 实现 - 创建脚本处理 `src/main/scripts/` 的打包(类似现有 forge.config.ts 中的 `packageAfterCopy` 钩子) - 考虑创建 `after-pack.cjs` 钩子处理 electron-builder 的特殊需求 #### 3.3 优化构建性能 - 实现开发文件清理(类似 ClawX 的体积优化) - 考虑平台特定资源裁剪 ### 第四阶段:测试与验证(预计 1-2 天) #### 4.1 开发构建测试 - 运行 `npm run dev`,验证开发服务器正常启动 - 测试热重载、主进程重载等功能 #### 4.2 生产构建测试 - 运行 `npm run build`,验证完整构建流程 - 检查输出目录结构是否正确 - 验证字节码保护是否生效 #### 4.3 安装包测试 - 生成各平台安装包(Windows、macOS、Linux) - 测试安装、运行、卸载流程 - 验证所有功能正常 #### 4.4 回归测试 - 确保现有功能不受影响 - 测试关键业务场景 ## 迁移后的构建流程 ### 开发构建流程 ``` npm run dev ``` 1. Vite 启动渲染进程开发服务器 2. `vite-plugin-electron` 编译主进程和预加载脚本 3. Electron 启动,连接开发服务器 ### 生产构建流程 ``` npm run build ``` 1. `vite build` 编译渲染进程 → `dist/` 2. `vite-plugin-electron` 编译主进程和预加载脚本 → `dist-electron/` 3. 字节码编译(生产模式) → 生成 `.jsc` 文件并更新入口 4. `electron-builder` 打包应用 → `release/` 目录 ### 平台特定打包 ``` npm run package:win # Windows 安装包 npm run package:mac # macOS 安装包 npm run package:linux # Linux 安装包 ``` ## 配置迁移对照表 | 当前配置 (zn-ai) | 目标配置 (ClawX 风格) | 迁移说明 | |-----------------|----------------------|----------| | `forge.config.ts` | `electron-builder.yml` | 功能映射,注意钩子转换 | | `vite.main.config.ts` | `vite.config.ts` 中的 `electron()` 配置 | 合并到统一配置 | | `vite.renderer.config.ts` | `vite.config.ts` 中的根配置 | 合并渲染进程配置 | | `vite.preload.config.ts` | `vite.config.ts` 中的 `electron()` 配置 | 作为第二个 electron 条目 | | `build/scripts/clean.js` | `electron-builder.yml` 的 `afterPack` 或构建脚本 | 清理逻辑集成到构建流程 | | `build/scripts/generateProdEntry.js` | 新的字节码编译插件 | 功能整合到 Vite 插件 | | `package.json` scripts | 更新为 ClawX 风格的脚本 | 保持功能,改进组织 | ## 风险评估与应对策略 ### 高风险项 1. **bytenode 集成失败** - **影响**:代码保护失效,可能影响商业化需求 - **应对**:先实现基础构建流程,再单独攻关保护机制;保留回滚方案 2. **依赖兼容性问题** - **影响**:构建失败或运行时错误 - **应对**:逐步迁移,分阶段测试;保持 electron 版本与现有依赖兼容 3. **目录结构变更导致路径错误** - **影响**:资源加载失败,功能异常 - **应对**:全面更新路径引用;使用别名简化路径管理 ### 中风险项 1. **跨平台打包问题** - **影响**:某些平台安装包生成失败 - **应对**:逐个平台测试验证;参考 ClawX 的平台特定配置 2. **构建性能下降** - **影响**:开发体验变差,构建时间延长 - **应对**:优化配置,启用缓存;对比新旧构建时间 ## 成功标准 1. **功能完整性**:所有现有功能在重构后正常工作 2. **构建成功**:开发构建、生产构建、各平台打包均成功 3. **性能相当**:构建时间不超过原有方案的 120% 4. **代码保护**:字节码保护机制有效,主进程代码得到保护 5. **可维护性提升**:配置更简洁,脚本更模块化 ## 后续优化建议 1. **依赖管理升级**:考虑从 npm 迁移到 pnpm,获得更好的依赖管理性能 2. **自动更新集成**:集成 electron-updater,实现自动更新功能 3. **构建缓存优化**:配置持久化缓存,加速构建过程 4. **CI/CD 集成**:将新构建流程集成到持续集成系统 ## 时间估算 | 阶段 | 任务 | 预计时间 | 备注 | |------|------|----------|------| | 第一阶段 | 基础配置迁移 | 2-3 天 | 包括依赖更新、配置创建、脚本更新 | | 第二阶段 | bytenode 保护机制重构 | 1-2 天 | 关键风险点,需要充分测试 | | 第三阶段 | 构建脚本优化 | 1-2 天 | 根据实际需求调整 | | 第四阶段 | 测试与验证 | 1-2 天 | 全面测试,确保质量 | | **总计** | | **5-9 天** | 实际时间取决于具体实现复杂度 | ## 结论 将 ClawX 项目的打包编译思路迁移到 zn-ai 项目是可行的,但需要谨慎处理 bytenode 代码保护机制的集成。重构后的构建系统将更现代化、模块化,且易于维护。建议按照上述计划分阶段实施,每个阶段完成后进行验证,确保整体项目稳定性。 **建议先进行第一阶段的基础配置迁移,验证基础构建流程可行后,再继续进行后续阶段。**