Langfuse React 组件清理实战基于 Component Cleanup Todo-List 的六步重构工作流【免费下载链接】langfuse Open source AI engineering platform: LLM evals, observability, metrics, prompt management, playground, datasets. Integrates with OpenTelemetry, LangChain, OpenAI SDK, LiteLLM, and more. YC W23项目地址: https://gitcode.com/GitHub_Trending/la/langfuse本篇指南以 Langfuse 仓库中.agents/skills/react-component-cleaner技能所配套的 component-cleanup-todolist.md 为核心骨架完整讲解如何对 React 组件执行一次严格化接口 → 清洗冗余 → 收敛复合组件 → 复核语义 → 补充 Storybook → 输出报告的全链路清理。读者将掌握冻结 props 类型、使用sweepyCLI 完成narrow-props、把 className/style 中的颜色与尺寸类收敛为 cva 变体、以Object.assign重写复合组件等一整套可落地的非破坏性重构手法并理解 Langfuse 前端设计系统web/src/components/design-system对组件接口的硬性规范。一、Todo-List 的定位与工作纪律Component Cleanup Todo-List 是react-component-cleaner技能SKILL.md执行时的操作手册技能本体规定做什么、按什么原则做Todo-List 规定按什么顺序做、每一步做完后做什么。1.1 前置审计与工具链在进入 Todo-List 之前技能要求先完整阅读 react-component-guidelines 对目标组件做一次基线审计审计对象仅限组件本身不包括调用点callsite 会在后续步骤中逐个检查。该指南明确了组件接口的验收标准最小接口Minimal Interface无未使用 props除非带来显著人体工学收益否则不设默认值避免可选 props不允许存在语义冲突的 props如同时存在onClick与onSelect显式状态Explicit States优先用Pick而非Omit用可辨识联合discriminated union表达互斥状态让不可能状态在类型层面无法表达封装Encapsulation除非组件本身是无样式的 headless 组件否则不应暴露className/styleprops确定性样式Deterministic Styling用 cva、条件或查找表显式表达变体避免依赖tailwind-merge的覆盖顺序去碰运气。清理全程依赖sweepyCLI技能中固定安装v0.1.0并锁定到指定 commit。该 CLI 默认是交互模式自动化场景可加--yes自动接受全部改动加--dry-run先预览再落地——这保证了每一步修改都是可审阅、可回退的。1.2 COMMIT 标记与格式化纪律Todo-List 在关键步骤后都标注了COMMIT含义是在创建 git commit 之前必须先跑完格式化与 lint 工具链。需要特别遵守的纪律包括只做指令内的修改不做任何额外编辑拿不准时向用户确认格式化 / lint 出现问题不要手改代码一律使用命令的 fix 变体commit message 不做特殊格式要求最终提交会被用户 squash 并审计todo 文件本身不要提交它只是执行参照物。二、Step 1把接口变成严格类型2.1 删除未使用的 props第一步检查组件的 props 是否全部被使用。任何未使用的 prop 直接删除并清理相关代码。2.2 冻结宽松的字符串 props核心检查项是className、style、size这类被定义为string的 prop是否可能被冻结为字符串字面量联合类型union of string literals且不影响现有所有调用点可以冻结直接用sweepy冻结该 prop然后COMMIT不可以冻结先检查先冻结调用点、再冻结 prop是否可行逐个调用点递归处理每执行一次冻结命令就COMMIT一次。这一步的价值在于把任意字符串都能传的宽接口收窄为只有这几个合法值能传的严格接口从类型系统层面阻止非法样式值的扩散。Langfuse 设计系统对这一点有硬性要求prop 值永远不能等于 Tailwind 类名例如sizemd合法而sizew-5 h-5非法见 design-system/README.md。三、Step 2清洗收窄后的接口3.1 默认值与可选 props 的清理在接口已收紧的基础上默认值凡不带来显著人体工学收益的默认值一律删除并更新调用点COMMIT可选 props凡可改为必填且不牺牲明显易用性的改为必填并更新调用点COMMIT。Langfuse 设计系统把无默认值 / 无可选 props列为组件最小接口的标准react-component-guidelines/SKILL.md这一步正是把该标准落到具体组件上。3.2 审计 className 与 style把裸类升级为变体这是整个清理中最核心的样式治理环节按顺序执行条件类上收检查是否存在条件性 className / style其实应该属于组件默认类。若是移入默认类并更新调用点COMMIT颜色类 → 颜色变体与颜色相关的类应定义为组件变体命名优先选用variant、type或level自行判断。把颜色类从 className / style 移入变体并更新调用点COMMIT尺寸类 → 尺寸变体与尺寸相关的类应定义为size变体同样移入并更新调用点COMMIT合并重复 props若出现两个表达同一语义的 props如同时有size与small删除冗余 prop 并更新调用点优先用sweepyCLI 替换 prop 值COMMIT上提残留类若仅剩的违规项是本应属于父组件的 className / style用sweepy将违规类上提lift到父组件COMMIT。关于变体的关键约束见 SKILL.md把类移入变体时变体必须完整拥有它改变的每一个 CSS 属性的全部类——即先移除基础类中的对应属性类再保证每个属性恰好由一个变体分支提供不得依赖cn、tailwind-merge、CSS 顺序或优先级来解决类冲突优先使用穷举查找表或cva变体。3.3 用可辨识联合合并依赖 props检查是否存在相互依赖的 props可以合并为可辨识联合discriminated union。若可以则合并——这一步不应导致调用点改动也不应引发 lint 问题COMMIT。这与组件指南中用可辨识联合表达意图而非依赖可空 / 可选让不可能状态在类型系统中无法表达的原则react-component-guidelines/SKILL.md完全一致。3.4 最后一步narrow-props收尾使用sweepy的narrow-props命令对接口做最终收窄COMMIT。四、Step 3审计复合组件Composite API4.1 先清洗成员再评估是否折叠如果组件属于复合 API例如Avatar、AvatarImage、AvatarFallback这种多成员集合必须先识别该 API 的所有公开导出成员然后保持现有的导出与组合语法不变对每个成员依次完成 Step 1 和 Step 2顺序为从叶子组件到根组件在进入下一个成员前先审计并更新当前成员的调用点在所有成员都清洗完成之前不要评估是否折叠 API。4.2 折叠 vs 保留的决策标准全部成员清洗完毕后审计所有调用点判断组合是否有意义应当折叠替换为单一组件并更新全部调用点COMMIT当且仅当同时满足成员始终表达一个固定的领域概念调用方无法有意义地控制成员的结构、顺序或生命周期使用差异可以通过少量语义化的父级 props清晰表达折叠后仍保留行为、语义、无障碍accessibility、事件处理与 ref 访问。应当保留复合 API当调用方确实需要对 children 进行重排、省略、重复或插入配置子组件特有行为为单个成员挂接 handler 或 ref把成员当作扩展点使用折叠会导致大量使用 slots 或 render props。4.3 单组件导出 Object.assign保留复合 API 时必须遵守一个文件只导出一个组件的规范通过Object.assign把子组件挂到导出组件上使用Alert.Title、Alert.Description语法而不是分别导出AlertTitle、AlertDescription。更新全部调用点后COMMIT。Langfuse 设计系统的这一规范在 design-system/README.md 中有完整示例源码中也有大量落地实现例如 Alert.tsx 的Object.assign(AlertRoot, { Title: AlertTitle, Description: AlertDescription })、Accordion.tsx、Tabs.tsx、RadioGroup.tsx。每个文件都遵守单文件单组件导出的目录结构约定文件夹名 组件名见 README.md。五、Step 4复核改动位置与 HTML 语义审计所有改动确认更新后的调用点在定位positioning与 HTML 语义上依然成立。如果发现问题把解决方案选项呈现给用户由用户决策不要擅自处理。常见的复核点包括折叠后的组件是否丢失了原有的role语义、事件冒泡行为、以及 ref 转发能力。六、Step 5为组件补充 Storybook 文档若目标组件尚不存在 Storybook story则创建之创建前先在仓库中查找相关的技能或文档指引Langfuse 设计系统约定每个组件目录下放置Button.stories.tsx见 design-system/README.md。完成后COMMIT。七、Step 6最终报告全部步骤完成后用 react-component-guidelines 对组件做二次复检并向用户输出报告内容包括本次所做的全部修改仍然存在的违规项如有对每一个被更新的调用点给出在应用中如何查看改动的详细指引组件现在接受哪些 prop、调用处应如何书写。八、从 Todo-List 反观 Langfuse 设计系统源码Todo-List 描述的目标状态在 Langfuse 设计系统中已经大面积落地可作为最佳实践参照变体治理几乎所有基础组件都用cva定义变体例如 Avatar.tsx 将sizesm/md/lg与shapecircle/rounded定义为显式变体并使用defaultVariantsAlert.tsx 的variant支持default/destructive/info/warningsize支持default/sm并定义了actionPosition、hasIcon等派生变体Pick 优先Alert.tsx 用PickVariantPropstypeof alertVariants, actionPosition | size | variant从 cva 变体类型中挑选公开 props与指南中始终优先Pick的要求一致复合组件 Object.assignAlert、Accordion、Tabs、RadioGroup 全部采用根组件 Object.assign挂子组件的写法不暴露 className/style设计系统规则明确禁止className/styleprops禁止任意值如#fff、12px布尔 props 必须用is/should前缀isLoading、shouldTruncate布局margin由父组件负责、根元素不含 margin——这些正是 Todo-List Step 2 期望达成的终态。换言之这份 Todo-List 与其说是一次性的清理清单不如说是把新组件打磨到 Langfuse 设计系统水准的验收流水线从类型收窄、变体收敛、联合类型重构到复合组件折叠决策与 Storybook 补全每一步都有明确的 COMMIT 检查点最终通过narrow-props收口再以 react-component-guidelines 复检闭环。【免费下载链接】langfuse Open source AI engineering platform: LLM evals, observability, metrics, prompt management, playground, datasets. Integrates with OpenTelemetry, LangChain, OpenAI SDK, LiteLLM, and more. YC W23项目地址: https://gitcode.com/GitHub_Trending/la/langfuse创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考