代码规范
工具链
| 工具 | 配置 | 命令 |
|---|---|---|
| Prettier | .prettierrc.json(无分号、单引号、行宽 100、尾逗号 all) | pnpm format / pnpm format:check |
| oxlint | .oxlintrc.json(忽略 dist/、node_modules/、test-results/) | pnpm lint |
| TypeScript | tsconfig.app.json(strict + noUncheckedIndexedAccess + noUnusedLocals) | pnpm typecheck |
一次性自证:pnpm check(格式检查 → 类型 → lint → 单测 → 生产构建)。
TypeScript 约束
strict: true:不允许隐式any、不允许可空值直接使用。noUncheckedIndexedAccess: true:rows[0]、record[key]的类型都带undefined。 用兜底值处理,不要用!断言绕过:tsconst owner = owners[index % owners.length] ?? '未分配' // 对 const owner = owners[index % owners.length]! // 错1
2verbatimModuleSyntax: true:类型导入必须写import type { X } from '...'。noUnusedLocals/noUnusedParameters:删掉比留着干净,不要用_前缀糊过去。
命名与结构
| 对象 | 约定 | 示例 |
|---|---|---|
| 文件 | kebab-case | data-table.tsx、page-pager.tsx |
| 组件 | PascalCase,命名导出 | export function DataTable |
| Hook | use- 开头文件名 + useXxx 导出 | hooks/use-mobile.ts |
| 纯逻辑 | 动词或名词短语 | flattenTree、resolvePalette |
| 类型 | PascalCase,props 用内联对象或 XxxProps | ConsoleLayoutProps |
| 测试 | 与被测对象同名 | src/test/unit/tree.test.ts |
组件内部顺序保持一致:类型 → 常量 → 主组件 → 辅助函数。
写组件时的硬约定
- 颜色只走语义 Token,不写
#086c6a、text-green-600这类具体色值。 - 文案进语言包(组件内部固定文案必须进;总览示例文案可以直接写中文)。
- 不引第三方依赖:图表自绘 SVG,动效用 CSS,不为了一个动效加一个库。
- 偏好只存浏览器并带
VITE_APP_STORAGE_PREFIX;服务端数据不进 Zustand。 - 副作用通过 prop 注入(
uploader、onMove、loadChildren、onSignOut),组件不直接调接口。 - 测试放
src/test/,不与被测文件并排。
注释
只解释"为什么",不重复"做了什么"。
踩过的坑要留下原因,例如:
tsx// 结构只由属性决定:否则清空按钮出现/消失会重挂载输入框,连续输入会丢焦点。1不写"照抄自 xx 项目"这类溯源注释:
.claude之外的读者只关心为什么这么写,来源信息放文档里。
提交前钩子与 CI
| 位置 | 内容 |
|---|---|
.githooks/pre-commit | 格式检查 + 类型 + lint + 单元测试(提交被拦过一次就算生效) |
.github/workflows/ci.yml | pnpm install --frozen-lockfile → pnpm check → Playwright → 上传 test-results/ |
首次克隆后执行一次:
bash
git config core.hooksPath .githooks1
钩子和 CI 跑的是同一组命令,本地过了 CI 基本不会挂;不能靠删用例或跳过来让校验变绿。