Files
ttstd-3d-director/README-PACKAGE.md
tongtongstudio b9fd289caf chore: 迁移到 pnpm 并更新打包与测试文档
- 用 pnpm 替换 npm,锁定 pnpm@10.33.0,删除 package-lock.json 相关说明
- package.json 将渲染层依赖移入 devDependencies,减小 app.asar 体积
- 新增 electron:smoke 冒烟脚本与 icon 生成脚本
- win 平台设置 AppUserModelID,修复任务栏图标归组
- 清理 tsBuildInfoFile 输出路径至 node_modules/.tmp
- 更新测试断言以匹配画幅遮罩、取景器缩放与模型库外部资产行为
- README 与打包指南补充 pnpm、镜像与常见问题说明
2026-09-16 20:03:57 +08:00

5.9 KiB
Raw Permalink Blame History

一力三期BMS - 故事AI导演工作台 打包指南

本文件是打包的唯一权威说明。使用说明.txt 为同内容的纯文本简版。

快速打包

双击运行 build-electron.bat,等待完成即可。

打包步骤详解

1. 环境准备

确保已安装:

  • Node.js 18+(下载地址:https://nodejs.org)
  • pnpm(npm i -g pnpm;工程根目录 package.json 已用 packageManager 锁定 pnpm 10.33.0)

本工程使用 pnpm,pnpm-lock.yaml 是唯一的锁文件,不再使用 package-lock.json。

2. 安装依赖

pnpm install

3. 构建前端

pnpm run build

4. 打包exe

pnpm run electron:build:win

5. 查看结果

打包完成后,在 release 目录找到:

  • 故事AI导演工作台 Setup 1.0.0.exe(安装包)

给用户使用

用户只需:

  1. 双击安装包
  2. 按提示安装(可自定义安装目录)
  3. 桌面出现快捷方式
  4. 双击打开即可使用

应用特性

  • ✅ 无需安装任何运行时
  • ✅ 桌面原生窗口体验
  • ✅ 自动创建桌面快捷方式
  • ✅ 支持自定义安装目录
  • ✅ 支持开始菜单快捷方式

自定义配置

修改窗口大小

编辑 electron/main.cjs:

mainWindow = new BrowserWindow({
  width: 1400,   // 修改宽度
  height: 900,   // 修改高度
  // ...
});

修改应用名称

编辑 package.json:

{
  "build": {
    "productName": "你的应用名称"
  }
}

修改应用图标

  1. 准备一个 256x256(建议 512x512)的 PNG 图标
  2. 命名为 icon.png 放到 public 目录
  3. 重新打包

public/icon.png 已随仓库提供,可用零依赖脚本重新生成:

python scripts/generate_icon.py

常见问题

Q: 打包失败怎么办?

A: 按顺序尝试:

  1. 删除 node_modules 文件夹
  2. 重新执行 pnpm install
  3. 再次打包

⚠️ 不要手动删除 node_modules 里的单个包(例如 node_modules/electron)。 绕过包管理器删包会让 pnpm 仍以为该依赖已安装,反而得到缺失或空壳的依赖目录。

Q: electron 二进制下载不下来?

A: 工程根目录 .npmrc 已配置 electron_mirror / electron_builder_binaries_mirror 指向 npmmirror。若仍失败,可临时设置:

set ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/
pnpm install

Q: exe文件太大?

A: Electron应用包含完整的Chromium浏览器引擎,这是正常的。打包后约 77MB。

Q: 安装后打不开?

A: 尝试:

  1. 右键以管理员身份运行
  2. 检查杀毒软件是否拦截
  3. 确保系统是Windows 10+

Q: 如何开发调试?

A: 运行:

pnpm run electron:dev

这会同时启动开发服务器和Electron窗口,支持热更新。

想额外验证"打包后的 dist 能否被 Electron 正常加载",可运行冒烟脚本:

pnpm run electron:smoke

冒烟脚本会依次确认:dist/index.html 能加载、React 成功挂载、渲染层没有报错。 它同时也验证了 dist 是自包含的(不依赖 node_modules)。

Q: 冒烟脚本在 CI / 远程桌面报错?

A: 无 GPU 的环境需要额外参数:

pnpm exec electron --use-angle=swiftshader --use-gl=angle --no-sandbox scripts/test-electron.cjs
  • --use-angle=swiftshader --use-gl=angle:走软件渲染。不加会报 THREE.WebGLRenderer: A WebGL context could not be created
  • --no-sandbox:部分受限沙箱里不加会导致页面加载直接 ERR_FAILED (-2)

普通桌面(有显卡)直接 pnpm run electron:smoke 即可,不需要这些参数。

Q: 冒烟脚本报 Cannot read properties of undefined (reading 'whenReady')?

A: 当前终端设置了 ELECTRON_RUN_AS_NODE,Electron 被强制退化成纯 Node, require('electron') 只返回二进制路径。清掉该变量再运行:

unset ELECTRON_RUN_AS_NODE     # bash
set ELECTRON_RUN_AS_NODE=      # cmd
Remove-Item Env:ELECTRON_RUN_AS_NODE   # PowerShell

脚本已内置该检测,遇到时会直接打印这条提示而不是抛 TypeError。

技术说明

  • 前端框架: React + TypeScript
  • 3D引擎: Three.js + React Three Fiber
  • 构建工具: Vite
  • 桌面框架: Electron
  • 打包工具: electron-builder
  • 包管理器: pnpm

为什么 dependencies 是空的

渲染层需要的所有库(three / react / zustand…)都被 Vite 打包进了 dist/assets/*.js, 主进程 electron/main.cjs 只 require('electron') 和 require('path')。

因此这些包全部放在 devDependencies:它们是构建期依赖,运行时不需要 node_modules。 electron-builder 默认会把 dependencies 里的包整棵拷进 app.asar——如果把它们留在 dependencies,app.asar 会从约 1 MB 膨胀到约 138 MB,安装包也跟着变大。

新增依赖时请同样放进 devDependencies,除非它确实要在运行时被 require。

文件结构

storyai-3d-director-desk/
├── electron/                 # Electron主进程
│   └── main.cjs              # 主进程入口(CommonJS,无 preload)
├── scripts/
│   ├── generate_icon.py      # 生成 public/icon.png
│   └── test-electron.cjs     # 加载 dist 的冒烟脚本
├── src/                      # 前端源码
├── public/                   # 静态资源(含 icon.png)
├── dist/                     # 构建输出
├── release/                  # 打包输出
├── docs/                     # 设计文档
├── package.json              # 项目配置
├── .npmrc                    # pnpm / 镜像配置
├── build-electron.bat        # 一键打包脚本
└── README-PACKAGE.md         # 本文档

更新日志

v1.0.0

  • 初始版本
  • 支持Windows打包
  • 支持桌面快捷方式
  • 迁移到 pnpm(package-lock.json → pnpm-lock.yaml)