Skip to content
Clone

ui

Vite + React 19 + TypeScript + Tailwind v4 + Alova,项目结构遵循 Feature-Sliced Design v2.1。

命令

bun run dev        # 启动开发服务器
bun run build      # tsc -b && vite build
bun run lint       # oxlint
bun run lint:fsd   # Steiger —— 官方 FSD 结构校验
bun run gen:api    # 依据 openapi.json 重新生成 src/shared/api

目录结构

当前采用最小可用分层(app + pages + shared)。features/、entities/ 只在 「同一段代码被多处实际使用且边界稳定」时才创建,不要提前建空目录; widgets/ 层不推荐采用。

src/
  app/                    ← 应用初始化:入口、路由、全局样式、providers
    index.tsx             ← 入口(index.html 指向这里)
    routes/router.tsx     ← 路由表,唯一允许 import pages 的地方
    shell/providers.tsx   ← 全局 Provider 组合(Redux / QueryClient / theme…)
    styles/index.css      ← 全局样式(Tailwind 入口)
  pages/                  ← 路由级组合,页面自己拥有的逻辑都留在这里
    home/
      ui/home-page.tsx
      index.ts            ← 切片公共 API
    not-found/
      ui/not-found-page.tsx
      index.ts
  shared/                 ← 无业务逻辑的基础设施,按 segment 划分、无 slice
    ui/                   ← UI kit(Button…),公共 API 在 ui/index.ts
    api/                  ← Alova 实例与 OpenAPI 生成代码(勿手改,见 gen:api)

约定

  • 导入方向:app → pages → widgets → features → entities → shared,只能向下依赖, 同层 slice 之间禁止互相 import。

  • 公共 API:外部只能通过 slice 的 index.ts(shared 则是每个 segment 的 index.ts)导入。

    import { Button } from '@/shared/ui' // ✅
    import { Button } from '@/shared/ui/button' // ❌ 绕过公共 API
    
  • 路径别名:@/app @/pages @/widgets @/features @/entities @/shared 在 tsconfig.app.json 与 vite.config.ts 两处保持同步。

  • 非 auth 跳转一律走 react-router:auth 流程之外的页面禁止 <a href> 与 window.location 整页跳转,只用 Link / useNavigate,保证 SPA 内最小化切换 (scripts/lint-nav.mjs 强制,已并入 bun run lint)。

  • 文件命名按业务域,不用技术角色:model/user.ts 而不是 model/types.ts。

  • shared 不含业务逻辑;CRUD 与鉴权 token 属于 shared/api / shared/auth, 不要为此新建 user entity。

  • Pages first:拿不准放哪里就留在页面里,重复不是下沉的充分条件。

新增页面:建 pages/<name>/ui/<name>-page.tsx + index.ts,再到 src/app/routes/router.tsx 注册路由。

注意(Windows + WSL)

工作区通过 \\wsl.localhost\... 访问时,bun 无法回写 bun.lock,Windows 侧 node 也解析不了部分包的入口(vite build 会报 plugin-react 入口错误)。 安装依赖与运行 dev / build / lint:fsd 建议在 WSL 内执行。