# ui Vite + React 19 + TypeScript + Tailwind v4 + Alova,项目结构遵循 [Feature-Sliced Design v2.1](https://fsd.how)。 ## 命令 ```bash 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/` 层不推荐采用。 ```text 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`)导入。 ```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 流程之外的页面禁止 `` 与 `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//ui/-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 内执行。