前端是 Yarn 4 单仓。日常工作是一组固定的小命令,一次性跑遍所有 workspace。提交落地前,Husky + lint-staged 会格式化并 lint 暂存文件,commitlint 强制 Conventional Commits。
UI 页面切片还需遵守 页面开发 与
Design System 1.2。yarn scaffold:page、yarn dev:ui 和
yarn ui:check 是后续目标命令,当前尚未实现;现阶段仍使用本文列出的实际命令。
1. 安装
cd frontend
# 严格按 lockfile 安装——yarn.lock 不同步则失败yarn install --immutableYarn 4.17.0 经 packageManager 字段固定,release 内嵌在 .yarn/releases/yarn-4.17.0.cjs,因此无需全局安装即可用对版本。.yarnrc.yml 设 nodeLinker: node-modules(经典落盘模块,非 PnP)与 npmRegistryServer: https://registry.npmmirror.com/(中国 npm 镜像)。
2. workspace 级脚本
以下命令从 frontend/ 根运行,经 yarn workspaces foreach -A 扇出到每个 workspace:
# 先验证依赖,再依次执行静态、类型、构建和格式化任务。yarn install --immutable # 严格安装yarn lint # yarn workspaces foreach -A run lintyarn typecheck # yarn workspaces foreach -A run typecheckyarn build # yarn workspaces foreach -A run buildyarn format # prettier --write .build 脚本在各 workspace 不统一——分清差异:
| Workspace | build 做什么 |
|---|---|
packages(@bitz/*) | tsc --noEmit |
@bitz/app | tsc --noEmit && vite build |
@bitz/app-mobile | yarn build:h5(Taro,非 tsc) |
所以从根跑 yarn build 是一次全量类型检查(packages + Web 应用)加 Web bundle 加移动端 H5 bundle。要只跑单个 workspace,用 Yarn 的 workspace 选择器:
yarn workspace @bitz/app build # 只 Web 应用yarn workspace @bitz/app-mobile build # 只移动端壳(H5)yarn workspace @bitz/platform-sdk build # 只 SDK package根 package.json 还接了移动端便利脚本:yarn dev、yarn dev:mobile、yarn dev:mobile:weapp、yarn dev:mobile:harmony、yarn build:mobile:android、yarn build:mobile:ios、yarn build:mobile:harmony、yarn mobile:android:open、yarn mobile:ios:open。各自产出见 移动端套壳。
3. 重新生成后端 client
# 后端产出 artifact(先跑)scripts/build/export-openapi.sh # → artifacts/openapi/openapi-v1.json
# 重新生成 client 类型——注意从 packages/platform-sdk 到仓库根是三个 ../yarn workspace @bitz/platform-sdk generate-client# → openapi-typescript ../../../artifacts/openapi/openapi-v1.json \# -o src/client/generated.d.ts
# CI 守护静默 driftscripts/build/check-openapi-drift.sh重新生成后,yarn typecheck 会把每个引用了已变 DTO 的调用点暴露成类型错误。不要用手写 interface 消除这些错误;应修正调用点或明确更新 schema 别名。
4. 提交规范
提交遵循 Conventional Commits,由 commitlint + @commitlint/config-conventional 强制:
<type>(<scope>): <subject>type取约定集合(feat、fix、docs、refactor、test、chore…)。- 允许中文 subject——commitlint 不强制 ASCII。
scope可选但鼓励,单仓里更清晰(如feat(platform-sdk): …)。
Husky 跑两个钩子:
- commit-msg →
yarn commitlint --edit "$1" - pre-commit →
yarn lint-staged
lint-staged 用 Prettier 格式化暂存文件,并对暂存的 *.{ts,tsx} 跑 ESLint --fix。失败即阻断提交。
{ "*.{js,cjs,mjs,ts,tsx,json,md,css}": ["prettier --write"], "*.{ts,tsx}": ["eslint --fix"]}Prettier 配置(prettier.config.cjs):singleQuote: true、semi: true、trailingComma: 'all'、printWidth: 100。ESLint(eslint.config.js,flat config)继承 @eslint/js recommended + typescript-eslint recommended;仅有的两条自定义规则是 @typescript-eslint/no-explicit-any: 'off' 与 no-unused-vars(warn,忽略 ^_ 参数)。今天没有 import 边界或 jsx-a11y 强制。
5. 提交前预期
改动可推送前,这四项必须全过:
# 与 CI 保持同一组提交前门禁。yarn install --immutableyarn lintyarn typecheckyarn build它们与 CI 闸门一致。yarn build 已对每个 workspace 跑过 tsc --noEmit(移动端除外,它用 Taro 构建),所以类型错误会在打包前让构建失败。
6. 测试
今天只有三个 package 有 test 脚本,都用 Vitest(vitest run / watch 用 vitest):
| Package | 有 test? | 值得注意的测试文件 |
|---|---|---|
@bitz/widgets | 有 | server-data-table.test.tsx、app-shell.test.tsx、permission-gate.test.tsx |
@bitz/platform-sdk | 有 | auth-session.test.ts、app-error.test.ts、api.test.ts、contracts.test.ts |
@bitz/i18n | 有 | (vitest) |
@bitz/components、editor、hooks、utils、materials、scripts | 无 | — |
前后端之间的架构 drift 由 scripts/build/check-openapi-drift.sh 守护,而不是前端测试。
7. 开发工具
- Locator(Web,仅 dev):
serve模式下@rolldown/plugin-babel+@locator/babel-jsx,加上NODE_ENV === 'development'时main.tsx调setupLocatorUI()。⌥-点击任意元素打开其源码。 - TailwindInspector:一个
@bitz/widgets调试组件(在home路由渲染),悬停时检查 Tailwind 类。经 widgets barrel 的export *再导出。
8. 不要提交的内容
前端的 .gitignore(及 subtree 迁入)已排除这些——保持如此:
node_modules/dist/、build/.yarn/cache(Yarn 4 +node-moduleslinker 无需进 git)- 原生平台构建产物(
android/、ios/、harmony/) - IDE 文件与密钥
9. 审一次贡献者改动
- 确认
yarn install --immutable成功——lockfile 同步。 - 确认
yarn lint、yarn typecheck、yarn build全过。 - 若后端契约变化,重新导出 OpenAPI、生成 client,并修正受影响调用点;禁止复制 DTO 字段。
- 确认提交信息符合 Conventional Commits(允许中文 subject)。
- 若新增依赖,确认它在正确 workspace 的
package.json里,而非根——除非确属共享。
10. 源核对
# 确认固定的工具链与 workspace 脚本。sed -n '1,60p' frontend/package.jsoncat frontend/commitlint.config.cjscat frontend/.yarnrc.ymlls frontend/.husky
# 确认哪些 package 真的有 test 脚本。rg -n '"test"' frontend/packages/*/package.json