- Updated `generateUUID` function for improved readability and performance. - Deleted `logger.ts`, `other.ts`, `request.ts`, `storage.ts`, `tansParams.ts`, and `validate.ts` as they were no longer needed. - Simplified TypeScript configuration by removing unnecessary paths and aliases. - Enhanced Vite configuration for better project structure and maintainability.
18 KiB
18 KiB
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)
完整构建命令依次执行以下步骤:
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 虚拟存储,收集所有传递依赖。
步骤:
- 解析
node_modules/openclaw的真实路径(跟随 pnpm 符号链接) - 确定 openclaw 所在的虚拟存储
node_modules目录(例如.pnpm/openclaw@版本/node_modules/) - BFS 遍历:
- 扫描虚拟存储
node_modules下的所有包(排除.bin) - 对每个包解析真实路径,记录包名与路径
- 找到该包自身的虚拟存储
node_modules,继续遍历其依赖
- 扫描虚拟存储
- 跳过开发依赖(如
typescript、@playwright/test)和特定作用域包(如@types/) - 将收集到的所有包复制到
build/openclaw/node_modules/(扁平化结构) - 去重处理:相同包名只保留首次遇到的版本(避免版本冲突)
- 清理:移除开发文档、测试目录、源码映射、类型定义等无用文件
- 修补已知问题模块:
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 字符限制)
体积优化
- 开发文件移除:删除
.d.ts、.map、测试目录、文档等 - 平台特定裁剪:
koffi本地库:只保留目标平台架构的预构建二进制文件- 作用域本地包(如
@napi-rs/canvas-*、@img/sharp-*):移除非目标平台变体
- 大文件移除:删除
node-llama-cpp/llama、pdfjs-dist/legacy等非必需大目录
兼容性修补
- CJS/ESM 互操作:
lru-cache旧版本缺少命名导出,通过追加exports.LRUCache补丁解决https-proxy-agent补充require导出条件,避免循环依赖错误
- Windows 控制台隐藏:修补 spawn 调用,添加
windowsHide: true选项 - 插件 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 应用复杂依赖管理的深刻理解,主要特点包括:
- 深度 pnpm 集成:专门处理虚拟存储的依赖收集,确保运行时完整性。
- 分层打包:将 OpenClaw 核心、插件、技能分别打包,模块清晰。
- 跨平台优化:针对各平台特性进行资源裁剪、性能优化与体验改进。
- 兼容性保障:主动修补第三方模块的 CJS/ESM 互操作问题,确保 Electron 40+(Node.js 22+)稳定运行。
- 构建效率:通过 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插件实现)
当前构建流程:
- 开发构建:
pnpm run dev - 生产构建:
pnpm run package、pnpm run build:encrypt - 自定义脚本:
clean.js、generateProdEntry.js用于清理和生成字节码入口
重构目标
将 ClawX 项目的现代化构建打包思路应用于 zn-ai 项目,主要目标:
- 统一构建配置:使用单个
vite.config.ts替代多个 Vite 配置文件 - 迁移打包工具:从 electron-forge 迁移到 electron-builder
- 优化构建流程:采用模块化构建脚本,提高可维护性
- 保持代码保护:保留或改进 bytenode 字节码保护机制
- 提升跨平台体验:借鉴 ClawX 的平台特定优化策略
可行性评估
可行方面
- 技术栈兼容性:Vite + Electron 组合在两个项目中都得到验证
- 配置迁移:Vite 配置可以合并,别名映射可以统一
- 打包工具迁移:electron-builder 功能覆盖 electron-forge,且配置更简洁
- 脚本模块化:ClawX 的脚本设计可以作为参考
挑战与风险
- bytenode 集成:ClawX 未使用字节码保护,需要设计新的集成方案
- 依赖管理差异:zn-ai 使用 npm,ClawX 使用 pnpm 虚拟存储,依赖收集策略可能不同
- 目录结构调整:需要适应新的输出目录结构(
dist/、dist-electron/) - 现有功能兼容性:确保所有现有功能在重构后正常工作
详细实施步骤
第一阶段:基础配置迁移(预计 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 开发构建测试
- 运行
pnpm run dev,验证开发服务器正常启动 - 测试热重载、主进程重载等功能
4.2 生产构建测试
- 运行
pnpm run build,验证完整构建流程 - 检查输出目录结构是否正确
- 验证字节码保护是否生效
4.3 安装包测试
- 生成各平台安装包(Windows、macOS、Linux)
- 测试安装、运行、卸载流程
- 验证所有功能正常
4.4 回归测试
- 确保现有功能不受影响
- 测试关键业务场景
迁移后的构建流程
开发构建流程
pnpm run dev
- Vite 启动渲染进程开发服务器
vite-plugin-electron编译主进程和预加载脚本- Electron 启动,连接开发服务器
生产构建流程
pnpm run build
vite build编译渲染进程 →dist/vite-plugin-electron编译主进程和预加载脚本 →dist-electron/- 字节码编译(生产模式) → 生成
.jsc文件并更新入口 electron-builder打包应用 →release/目录
平台特定打包
pnpm run package:win # Windows 安装包
pnpm run package:mac # macOS 安装包
pnpm 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 风格的脚本 | 保持功能,改进组织 |
风险评估与应对策略
高风险项
-
bytenode 集成失败
- 影响:代码保护失效,可能影响商业化需求
- 应对:先实现基础构建流程,再单独攻关保护机制;保留回滚方案
-
依赖兼容性问题
- 影响:构建失败或运行时错误
- 应对:逐步迁移,分阶段测试;保持 electron 版本与现有依赖兼容
-
目录结构变更导致路径错误
- 影响:资源加载失败,功能异常
- 应对:全面更新路径引用;使用别名简化路径管理
中风险项
-
跨平台打包问题
- 影响:某些平台安装包生成失败
- 应对:逐个平台测试验证;参考 ClawX 的平台特定配置
-
构建性能下降
- 影响:开发体验变差,构建时间延长
- 应对:优化配置,启用缓存;对比新旧构建时间
成功标准
- 功能完整性:所有现有功能在重构后正常工作
- 构建成功:开发构建、生产构建、各平台打包均成功
- 性能相当:构建时间不超过原有方案的 120%
- 代码保护:字节码保护机制有效,主进程代码得到保护
- 可维护性提升:配置更简洁,脚本更模块化
后续优化建议
- 依赖管理升级:考虑从 npm 迁移到 pnpm,获得更好的依赖管理性能
- 自动更新集成:集成 electron-updater,实现自动更新功能
- 构建缓存优化:配置持久化缓存,加速构建过程
- CI/CD 集成:将新构建流程集成到持续集成系统
时间估算
| 阶段 | 任务 | 预计时间 | 备注 |
|---|---|---|---|
| 第一阶段 | 基础配置迁移 | 2-3 天 | 包括依赖更新、配置创建、脚本更新 |
| 第二阶段 | bytenode 保护机制重构 | 1-2 天 | 关键风险点,需要充分测试 |
| 第三阶段 | 构建脚本优化 | 1-2 天 | 根据实际需求调整 |
| 第四阶段 | 测试与验证 | 1-2 天 | 全面测试,确保质量 |
| 总计 | 5-9 天 | 实际时间取决于具体实现复杂度 |
结论
将 ClawX 项目的打包编译思路迁移到 zn-ai 项目是可行的,但需要谨慎处理 bytenode 代码保护机制的集成。重构后的构建系统将更现代化、模块化,且易于维护。建议按照上述计划分阶段实施,每个阶段完成后进行验证,确保整体项目稳定性。
建议先进行第一阶段的基础配置迁移,验证基础构建流程可行后,再继续进行后续阶段。