桌面与远程资源准备及打包
本文说明 @zcode/desktop 的构建脚本如何在生产构建前准备本地运行资源与可选远程资源,并区分资源准备、构建与打包入口。
目的与范围
面向维护桌面构建和 CI 的开发者:重点是桌面包的脚本入口、prepare-runtime-assets.mjs 的分支及执行顺序,以及可见的环境开关。远程预构建资源的下载与打包算法、各原生辅助程序的内部实现、安装包签名和发布流水线不在本页范围内;它们由各自的脚本负责,本页不推断未读取的实现。若需理解远端资源内容,请从 prepare-prebuilds.mjs 入手;若需理解安装包构造,请参阅 bundle.mjs。
概述
桌面包把「准备资源」和「执行生产构建」分成两个脚本:build 先运行 prepare:runtime-assets,再运行 build:no-runtime-assets;后者运行 prepare:build-meta 与 run-production-build.mjs。bundle 则是单独的脚本入口,不能仅凭脚本声明断言它自动执行完整资源准备流程。脚本定义
资源准备器根据目标平台选择任务:未设置跳过开关时先准备远程资源;始终准备本地 agent bundle;按 native-search 发布计划、Windows 导入开关和 macOS 目标决定是否增加其他准备步骤。每一步通过 runCommand 启动 pnpm,并在 finally 中输出持续时间。准备器实现
架构
Source: package.json, prepare-runtime-assets.mjs
图中 Orchestrator 到可选任务的箭头表示条件调用,并非所有平台都会执行。图示 build 的脚本编排顺序;没有把独立的 bundle 误画成 build 的隐含下一步。
实现与执行顺序
入口的职责划分
| 入口 | 已验证的行为 | 适用场景 |
|---|---|---|
prepare:runtime-assets | 执行 scripts/prepare-runtime-assets.mjs | 单独准备桌面运行资源 |
prepare:remote-assets | 执行仓库级 scripts/prepare-prebuilds.mjs | 单独触发远端资源准备;其内部细节不在已读取源代码中 |
build:no-runtime-assets | 先准备构建元数据,再调用 run-production-build.mjs | 资源已由其他步骤准备时的构建入口 |
build | 先准备运行资源,再调用 build:no-runtime-assets | 完整桌面构建入口 |
bundle | 调用 scripts/bundle.mjs | 独立打包入口;其选项与实际产物需核对该脚本 |
上述入口均来自 桌面包脚本声明。仓库根目录另有 prepare:desktop-runtime 和 prepare:remote-assets 两个转发到桌面包的命令,以及 bundle:desktop 转发入口。根脚本对应声明
目标平台与条件任务
准备器用 getTargetPlatform() 获取 os 与 arch,传给 resolveNativeSearchReleasePlan;是否增加 prepare:native-search 由返回计划的 enabled 属性决定。Windows 浏览器导入辅助程序只有在目标为 win32 且环境变量严格等于字符串 1 时才加入;macOS 窗口边界辅助程序在目标为 darwin 时加入。注释说明后者缺少 swiftc 时由其自己的脚本处理跳过,本文不进一步推断其实现。平台选择与注释
1const target = getTargetPlatform();
2const nativeSearchReleasePlan = resolveNativeSearchReleasePlan({
3 platform: target.os,
4 arch: target.arch,
5});
6// Windows Chrome 导入入口未启用,默认构建继续编译 helper 会增加 CI 时间和发布签名面。
7// 保留显式开关,后续恢复入口时仍可复用既有原生实现和供应链校验。
8const shouldPrepareWindowsBrowserImportHelper =
9 target.os === "win32" && process.env.ZCODE_ENABLE_WINDOWS_BROWSER_IMPORT === "1";
10// CUA 权限浮窗的吸附数据源。仅 macOS;缺 swiftc 时脚本内部自行降级为跳过(浮窗 fail-open
11// 到屏幕底部,仍可用),所以无条件挂在 darwin 上不会让构建变脆。
12const shouldPrepareMacosWindowBounds = target.os === "darwin";Source: prepare-runtime-assets.mjs
任务数组固定以 prepare:agent-bundle 开始,再依次拼接符合条件的 native-search、Windows 导入、macOS 窗口边界任务;注释区分本地 agent 的 JS bundle(由应用的 Electron Node runtime 执行)和远程跨平台原生二进制。native-search 的归档按注释随仓库分发,该步骤是本地解包校验,不需要下载源配置。资源角色与任务数组
1const localRuntimeScripts = [
2 "prepare:agent-bundle",
3 ...(nativeSearchReleasePlan.enabled ? ["prepare:native-search"] : []),
4 ...(shouldPrepareWindowsBrowserImportHelper ? ["prepare:browser-import-helper"] : []),
5 ...(shouldPrepareMacosWindowBounds ? ["prepare:macos-window-bounds"] : []),
6];Source: prepare-runtime-assets.mjs
核心流程
Source: prepare-runtime-assets.mjs
远端资源在本地任务循环之前执行,且只由 ZCODE_SKIP_REMOTE_ASSETS 控制是否跳过;跳过远端资源不等于跳过本地 agent 与平台相关步骤。runTimedPnpmScript 通过当前进程环境执行命令,工作目录固定为桌面包根目录;Windows 主机使用 pnpm.cmd,其他主机使用 pnpm。执行函数与分支 后续调用
用法示例
以下示例是项目实际脚本声明,不是臆造的命令组合。build 适用于需要资源准备的路径,build:no-runtime-assets 只承担元数据与生产构建;bundle 是分开的入口。
1"prepare:runtime-assets": "node scripts/prepare-runtime-assets.mjs",
2"prepare:remote-assets": "node ../../scripts/prepare-prebuilds.mjs",
3"build:no-runtime-assets": "pnpm prepare:build-meta && node scripts/run-production-build.mjs",
4"build": "pnpm prepare:runtime-assets && pnpm run build:no-runtime-assets",
5"bundle": "node scripts/bundle.mjs"Source: package.json
在准备器内部,实际启动与计时逻辑如下;finally 确保命令失败时仍会记录结束耗时,并不表示失败会被吞掉。
1function runTimedPnpmScript(scriptName) {
2 const startMs = Date.now();
3 console.log(`[ci][timer] prepare-runtime-assets:${scriptName} start`);
4 try {
5 runCommand(pnpmCommand, [scriptName], {
6 cwd: desktopRoot,
7 env: process.env,
8 });
9 } finally {
10 console.log(
11 `[ci][timer] prepare-runtime-assets:${scriptName} end duration_ms=${Date.now() - startMs}`,
12 );
13 }
14}Source: prepare-runtime-assets.mjs
配置选项
| 选项 / 输入 | 类型 | 默认 / 未设置时 | 作用 |
|---|---|---|---|
ZCODE_SKIP_REMOTE_ASSETS | 环境变量字符串 | 不跳过 | 严格等于 "1" 才跳过 prepare:remote-assets;注释指出 Windows 安装包构建任务无需 mock-cdn 远端资产时可避免串行跨平台资源准备耗时。 |
ZCODE_ENABLE_WINDOWS_BROWSER_IMPORT | 环境变量字符串 | 不启用 | 严格等于 "1" 且目标 OS 为 win32 时准备浏览器导入辅助程序。 |
getTargetPlatform() 的 os、arch | 函数返回的目标信息 | 具体值由目标平台模块决定 | 决定 native-search 发布计划及两种平台辅助任务;此页不推断其环境变量覆盖规则。 |
nativeSearchReleasePlan.enabled | 布尔条件 | 由 resolveNativeSearchReleasePlan 返回 | 决定是否运行 prepare:native-search。 |
证据:条件构造、跳过分支。不要将空值、true 或其他非 "1" 值视为开启开关。
脚本接口与失败边界
此能力主要通过包脚本而不是 HTTP API 暴露。脚本声明 提供 prepare:runtime-assets、prepare:remote-assets、build:no-runtime-assets、build、bundle。准备器内部的 runTimedPnpmScript(scriptName) 接收包脚本名称,调用 runCommand(pnpmCommand, [scriptName], { cwd: desktopRoot, env: process.env });函数没有显式返回值,抛错类型取决于未在此处展开的 runCommand 实现。调用实现
失败模式、并发与运维
- 准备器使用同步顺序的调用写法:先远端任务,再逐一遍历本地任务;没有在本文件中并行调度或重试。执行段
try/finally在命令结束或抛错时打印[ci][timer]耗时;没有catch或本地恢复分支。不要把日志出现理解为准备成功。计时函数ZCODE_SKIP_REMOTE_ASSETS=1只跳过远端准备并输出提示,本地步骤仍执行;该开关针对不需要 mock-cdn 远端资产的 Windows build job,使用前应确认自己的交付物是否需要远端资源。开关说明- 扩展本地准备步骤的明确挂载位置是
localRuntimeScripts;保持条件与目标平台匹配,并注意它们按照数组次序串行调用。子脚本内部是否下载、缓存或清理产物,在已读取的源代码中未核实。任务数组