# muse-studio 脚手架与核心基础设施搭建留痕 ## 任务背景 在根目录从零初始化前端用户端子项目 `muse-studio`(Vite + React + TS 结构),并完成路由、统一客户端、MSW 2.0 Mock、IndexedDB 及 Zustand 状态库等基础设施建设。 ## 关键工程实践与避坑指南 ### 1. TypeScript 6.0 严格模式兼容 #### (1) `erasableSyntaxOnly` 限制 - **现象**:当启用该规则时,TypeScript 6.0 禁用了 parameter properties 语法(如在 constructor 参数中直接写 `public code: string`)。 - **避坑**:声明异常类或常规类时,需采用标准 ES ES6 属性定义: ```typescript export class ApiError extends Error { public code: string; public status: number; constructor(code: string, message: string, status: number) { super(message); this.code = code; this.status = status; } } ``` #### (2) `exactOptionalPropertyTypes` 限制 - **现象**:在对象字面量中如果显式将可选属性设为 `undefined` 会报错。 - **避坑**:构造请求参数(如 RequestInit 的 `body`)时,避免传入 `body: undefined`。应采用动态属性扩展或先判断再赋值: ```typescript const options: RequestInit = { method: 'POST' }; if (data !== undefined) { options.body = JSON.stringify(data); } ``` #### (3) `baseUrl` 被废弃 - **现象**:TypeScript 6.0+ 将逐渐废弃 `baseUrl`,编译时会报 TS5101 错误。 - **避坑**:从 `tsconfig.app.json` 中直接移除 `"baseUrl"`,Vite + TS 依然能够通过相对位置正确解析 `"paths"`(别名映射)。 ### 2. pnpm 包管理构建脚本受阻 - **现象**:在新版 pnpm (v10/v11) 中,若存在未显式授权的构建脚本(如 `esbuild`, `msw`),任何 pnpm 命令在运行依赖完整性检查时都会抛出 `[ERR_PNPM_IGNORED_BUILDS]` 并强制中断。 - **解决方案**: 1. **本地开发**:在子项目根目录下创建 `.npmrc` 并添加以下白名单配置: ```ini only-built-dependencies[]=esbuild only-built-dependencies[]=msw ``` 2. **CI 或自动化编译**:如果依然受到全局白名单阻碍,可使用 `--ignore-scripts` 绕过依赖构建脚本检查: ```bash pnpm install --ignore-scripts ``` ### 3. MSW 2.0 模拟 SSE (Server-Sent Events) - **实现**:MSW 2.0 支持使用 `ReadableStream` 模拟 SSE 流式推送。在 Mock 处理器中可通过 `TextEncoder` 写入符合 EventSource 格式的缓冲行,并在 headers 中指定 `text/event-stream`。 ```typescript http.get('/api/ai/stream', () => { const encoder = new TextEncoder(); const stream = new ReadableStream({ async start(controller) { controller.enqueue(encoder.encode(`data: ${JSON.stringify({ type: 'chunk', content: '数据' })}\n\n`)); controller.close(); } }); return new HttpResponse(stream, { headers: { 'Content-Type': 'text/event-stream' } }); }) ``` ### 4. Zustand 4 严格模式类型推断 - **避坑**:在 Zustand Store 中,为了避免隐式 `any` 类型报错,建议统一使用柯里化方法传入泛型定义: ```typescript import create from 'zustand'; export const useUIStore = create()((set) => ({ ... })); ```