时长:30-40 分钟
9.1 Electron Builder 配置
9.1.1 多平台配置
- 配置位置:在
package.json的build字段中,通过mac、win、linux分别配置各平台产物与选项。 - 当前项目(节选):
- mac:
target: [{ target: 'dmg', arch: ['x64', 'arm64'] }],输出 DMG;category: 'public.app-category.developer-tools';identity: null表示不强制签名(开发或内部分发时可跳过签名)。 - win:
target: [{ target: 'nsis', arch: ['x64', 'arm64'] }],输出 NSIS 安装包;图标使用assets/icons/icon.ico。 - linux:
target: [{ target: 'AppImage', arch: ['x64', 'arm64'] }],输出 AppImage。 - 构建命令:
- 仅 Mac:
electron-builder --mac --x64 --arm64或electron-builder --mac dmg --x64 --arm64。 - 仅 Windows:
electron-builder --win --x64 --arm64。 - 仅 Linux:
electron-builder --linux --x64 --arm64。 - 多平台:
electron-builder -mwl(按需加--x64 --arm64)。 - 输出目录:
directories.output: "release",打包产物在项目根目录的release/下。
9.1.2 资源文件管理
- files:
指定被打进 app.asar 或应用包内的文件/目录;未列出的不会被打包。
- 当前项目(节选):
"files": [
"dist/**",
"electron/**",
"package.json",
"assets/icons/**",
"WebDriverAgent/photo-proxy/*/.js"
]
dist/**:Vite 构建后的前端静态资源。electron/**:主进程与 preload 脚本。package.json:应用元信息。assets/icons/**:应用图标。WebDriverAgent/photo-proxy/*/.js:photo-proxy 编译后的 JS(主进程动态加载用)。- extraResources:
不放进 asar、而是拷贝到应用资源目录(如 macOS 的 Contents/Resources)的文件,适合可执行文件、二进制、需直接路径访问的资源。
- 当前项目(节选):
"extraResources": [
{ "from": "commands", "to": "commands", "filter": ["*/"] },
{ "from": "photo-service/build/photo-service", "to": "photo-service", "filter": ["photo-service"] },
{ "from": "native/ios-screen-recorder/.build/release/ios-screen-recorder", "to": "commands/ios-screen-recorder", "filter": ["ios-screen-recorder"] }
]
commands:adb、hdc、ios、scrcpy、ffmpeg 等命令行工具及 WDA.ipa 等,主进程通过process.resourcesPath或getAppPath()解析后调用。photo-service:C++ 构建的 photo-service 可执行文件。ios-screen-recorder:Swift 构建的 iOS 录屏工具。- 为何用 extraResources:
asar 内文件为只读、且不能直接执行二进制;命令行工具和原生可执行文件必须放在 asar 外,通过文件系统路径访问。
9.1.3 签名配置
- mac:
- identity:
填写 Apple 开发者证书的 Developer ID Application 名称(如 "Developer ID Application: Your Name (TEAM_ID)");正式分发必须签名,否则 Gatekeeper 会拦截。
- 当前项目:
"identity": null,即不指定证书,打包出的应用为未签名或使用默认签名;适合内部分发或本机测试。 - afterSign:
钩子脚本,在签名完成后执行;可用于 notarize(公证)等。当前项目配置为 build/afterSign.cjs,脚本内仅 return true,可在此扩展公证或上传符号表等。
- win:
- 若需签名,在
win下配置certificateFile、certificatePassword等;或使用afterSign在打包后调用外部签名工具。 - 公证(macOS):
若对外分发,除签名外建议做 notarize,在 afterSign 中调用 notarize 相关工具,避免用户打开时被系统拦截。
9.1.4 自动更新
- Electron 方案:
使用 electron-updater(如 electron-builder 配套的 electron-updater)在应用内检查更新、下载并安装。
- 流程概要:
- 打包时配置
publish(如provider: 'generic',url: 'https://your-server.com/releases'),使 builder 生成latest.yml等元数据。 - 主进程在适当时机(如启动后、定时)调用
autoUpdater.checkForUpdates(),根据latest.yml判断是否有新版本。 - 若有更新,下载安装包并提示用户重启安装(或静默安装,视配置而定)。
- 当前项目:
未在 package.json 的 build 中配置 publish 和 electron-updater;若需自动更新,可增加 publish 配置并在主进程集成 electron-updater,将打包产物与 latest.yml 上传到内网或公网服务器供客户端拉取。
9.2 打包优化
9.2.1 体积优化
- 前端:
- 使用 Vite 生产构建(
vite build),自动 Tree-shaking、压缩 JS/CSS。 - 依赖按需引入(如 Element Plus 按需导入),减少 bundle 体积。
- 图片/字体等静态资源放
assets,Vite 会带 hash 并压缩;过大的资源可考虑 CDN 或懒加载。 - Electron:
files只包含必要项,避免把node_modules整包打进 asar(通常只打运行时依赖,devDependencies 不打进)。extraResources只放必要二进制(commands、photo-service、ios-screen-recorder),避免重复或无用文件。- 可选:使用
asarUnpack把部分需解压访问的文件排除在 asar 外,其余保持 asar 以加快读取。 - 原生/二进制:
- commands 目录下只保留当前平台需要的可执行文件(若做分平台打包,可按平台拷贝不同 commands)。
- photo-service、ios-screen-recorder 等按需编译,不携带多余符号或调试版本。
9.2.2 启动速度优化
- 主进程:
- 重量级模块(如 photo-proxy、URL Service)采用懒加载,在首次调用对应 IPC 时再
require/import,避免启动时全部加载。 - 避免在 main 顶层执行耗时 I/O 或网络请求,必要逻辑放到
app.on('ready')之后或异步初始化。 - 渲染进程:
- 首屏路由或 Tab 对应的组件可采用懒加载(
defineAsyncComponent+import()),减少首屏 JS 体积与解析时间。 - 前端资源使用 Vite 的代码分割(动态 import 会自动拆 chunk),避免单一大 bundle。
- Electron 启动参数:
可按需启用 --enable-features=... 或禁用部分 Chromium 特性,对启动时间影响较小,以稳定性优先。
9.2.3 资源压缩
- Vite:
生产构建默认对 JS/CSS 做 minify(esbuild/terser);可通过 build.minify、build.rollupOptions.output.manualChunks 等进一步控制。
- asar:
electron-builder 打包 asar 时会对文件做一定压缩;若不需要 asar 压缩可配置 asar: false(一般不推荐,会失去单文件与一定保护)。
- 静态资源:
图片可使用压缩工具或构建阶段压缩;字体子集化可减小体积。
9.2.4 代码分割
- 前端:
- Vite 会根据动态 import 自动做代码分割,生成多个 chunk;合理使用
import()懒加载路由或大组件即可。 - 若未使用路由,可按“平台面板”懒加载(如
const IOSDeviceSection = defineAsyncComponent(() => import('./IOSDeviceSection.vue'))),切换 Tab 时再加载对应 chunk。 - 当前项目:
vite.config.ts 未显式配置 manualChunks;依赖 Vite 默认行为即可。若分析后发现某依赖体积过大,可将其单独打成 chunk(如 manualChunks: { 'element-plus': ['element-plus'] })以利用缓存。
- 主进程:
Node 侧可按需动态 import() 大模块(如 photo-proxy、url-service),实现“逻辑上的分割”,减少启动时解析量。
9.3 CI/CD 实践
9.3.1 自动化构建
- 目标:在代码提交或打 tag 时自动执行“前端构建 + 依赖准备 + Electron 打包”,产出安装包或可执行文件。
- 脚本顺序(与当前
dist/dist:mac一致):
- 固定 Node 版本(如 nvm use 18.18.2)。
yarn build:photo-proxy:编译 photo-proxy 的 TypeScript → JS。yarn build:photo-service:编译 C++ photo-service(若 CI 环境有 cmake/make)。yarn build:Vite 前端构建,输出到dist/。electron-builder --mac --x64 --arm64(或--win、--linux),产出到release/。
- CI 示例(GitHub Actions 思路):
- 使用
actions/setup-node指定 Node 版本;可选actions/cache缓存node_modules与 Vite 缓存。 - macOS runner 下安装 Xcode Command Line Tools 或完整 Xcode(若需编译原生模块);Windows runner 下安装 Visual Studio Build Tools(若需 native 模块)。
- 执行上述脚本;将
release/*.dmg、release/*.exe、release/*.AppImage等产物上传为 Artifact 或发布到 Release。 - 当前项目:
根目录未配置主应用的 GitHub Actions;WebDriverAgent 子目录下有独立 workflow(如 wda-package、unit-test)。主应用若需 CI,可在仓库根目录新增 .github/workflows/build.yml,参照上述顺序编写 job。
9.3.2 自动化测试
- 目标:在 MR/PR 或主干提交时自动跑单测、静态检查,有条件可跑 E2E,防止明显回归。
- 可执行内容:
- Lint:
eslint .、vue-tsc --noEmit(若上 TypeScript)。 - 单测:
vitest run或jest(若已为 utils/纯逻辑编写单测)。 - E2E:Playwright 或 Electron 官方 test 方案,对“启动应用 → 关键操作”做少量冒烟(可选,因 Electron 需图形或虚拟显示)。
- 当前项目:
package.json 中有多组 test:* 脚本(如 test:photo-proxy、test:port-forward、test:binary 等),用于 photo-proxy 与连接相关的手动/本地验证;主应用前端暂无统一 test 或 test:unit。若引入 CI,可先加入 lint + 单测(若有),E2E 视环境再补。
9.3.3 自动化部署
- 目标:构建通过后,将安装包或可执行文件发布到内网/公网,供用户下载或自动更新拉取。
- 方式:
- GitHub Release:
CI 在打 tag 时构建,并将 release/*.dmg、*.exe、*.AppImage 及 latest.yml 上传到该 tag 的 Release 页面;客户端通过 electron-updater 指向 GitHub 的 release 地址即可检查更新。
- 自建服务器:
将产物上传到自建静态站或对象存储,配置 publish.url 与 latest.yml,客户端指向该地址。
- 内网分发:
上传到内网文件服务或制品库,通过内网链接或内部更新服务器下发。
- 版本与产物:
建议版本号与 package.json 的 version 或 tag 一致;产物命名可带版本与架构(如 小赢MobileTool-0.1.0-arm64.dmg),便于排查与回滚。
9.3.4 版本管理
- 版本号:
使用 package.json 的 version(如 0.1.0);Electron Builder 会将其写入产物名与元数据。可采用语义化版本(主.次.修订),或与内部版本号对齐。
- 与 Git 联动:
- 主干/开发分支:每次合并可自动构建并产出“最新开发版”安装包(如带
dev或 commit short sha)。 - 正式发布:打 tag(如
v0.1.0)触发构建并发布到 Release,同时更新version或由 CI 根据 tag 写回package.json。 - 自动更新兼容:
若使用 electron-updater,需保证 latest.yml 与安装包一一对应,且版本号递增;否则客户端可能无法正确检测更新或下载。
小结
- Electron Builder:通过
package.json的build配置多平台、files/extraResources管理资源、identity/afterSign处理签名与公证;自动更新需额外配置publish与electron-updater。 - 打包优化:控制
files/extraResources体积、主进程懒加载、前端代码分割与压缩,兼顾体积与启动速度。 - CI/CD:按“构建 → 测试 → 部署”串联脚本;版本与 tag 统一管理,便于发布与回滚。当前项目可在此基础上增加主应用 workflow,并与现有 WebDriverAgent 的 CI 并存。







Comments | NOTHING