本指南介绍项目的代码规范和开发约定。
项目使用 Biome 2.x 统一处理 linting 和 formatting,替代 ESLint + Prettier。
根目录 biome.json:
{
"$schema": "https://biomejs.dev/schemas/2.4.14/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git"
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"correctness": {
"noUnusedImports": "error",
"noUnusedVariables": "error"
},
"nursery": {
"useSortedClasses": "warn"
}
}
}
}# 检查代码
bun run lint
# 自动修复
bun run lint:fix
# 格式化
bun run format项目使用 commitlint + lefthook 强制 conventional commits。
<type>(<scope>): <description>| 类型 | 用途 |
|---|---|
feat | 新功能 |
fix | Bug 修复 |
chore | 构建/工具链变更 |
refactor | 重构(不改变行为) |
docs | 文档更新 |
test | 测试相关 |
ci | CI/CD 配置 |
perf | 性能优化 |
revert | 回滚提交 |
feat(ui): add Sheet component
fix(blog): correct date format in archive page
docs(readme): update installation guide
refactor(links): extract link validation logic使用 import type 导入类型:
import type { PostMeta } from "@/lib/mdx"
import type { ReactNode } from "react"使用 React.ComponentProps 继承原生属性:
function MyButton({
className,
...props
}: React.ComponentProps<"button">) {
return <button className={cn
| 类型 | 约定 | 示例 |
|---|---|---|
| 组件 | PascalCase | Button.tsx |
| 工具函数 | camelCase | formatDate.ts |
| 页面 | kebab-case | page.tsx |
| 布局 | kebab-case | layout.tsx |
| 测试 | *.test.ts(x) | button.test.tsx |
| MDX 内容 | kebab-case | getting-started.mdx |
需要交互的组件添加 "use client":
"use client"
import * as React from "react"
export function Counter() {
const [count, setCount] = React.useState(
默认使用服务端组件,无需特殊标记:
import { getAllPosts } from "@/lib/mdx"
export default async function BlogPage() {
const posts = await getAllPosts()
return <div>{/* ... */}</
useSortedClasses 自动处理cn() 函数合并条件类名| 断点 | 尺寸 | 用途 |
|---|---|---|
sm | 640px | 小屏设备 |
md | 768px | 平板/桌面分界 |
lg | 1024px | 桌面 |
xl | 1280px | 大屏 |
使用 .dark class 策略,通过 next-themes 管理。所有颜色 token 自动适配。
**/src/**/*.test.{ts,tsx}/// <reference types="vitest/globals" /> 获得全局类型/// <reference types="vitest/globals" />
import { describe, expect, it } from "vitest"
import { parseField } from "@iflux/utils"
describe("parseField", ()
e2e/ 目录e2e/web/、e2e/blog/、e2e/docs/ 等PLAYWRIGHT_BASE_URL 环境变量切换目标应用import { expect, test } from "../helpers/fixtures"
test.describe("Home Page", () => {
test.beforeEach(async ({ page }) => {