ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Langfuse 前端大型功能 Feature README 编写规范:用“所有权地图“管理复杂前端架构

Langfuse 前端大型功能 Feature README 编写规范:用“所有权地图“管理复杂前端架构 Langfuse 前端大型功能 Feature README 编写规范用所有权地图管理复杂前端架构【免费下载链接】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 前端团队通过一套名为frontend-large-feature-architecture的技能体系来约束这类功能的演进其中以Feature README功能 README作为每一块大型前端功能面向人类开发者与 AI Agent 的所有权地图owner map。本文以 feature-readmes.md 为骨架结合 Langfuse 仓库中 dashboard、tracing-tables、peek 等真实落地案例系统讲解 Feature README 的必填章节、状态所有权规则、性能与稳定性地图、现状诚实原则与增量更新方法帮助读者掌握一套文档驱动架构演进的工程实践。Feature README 是什么大型前端功能的所有权地图大型前端功能目录应当拥有一份简短的README.md它扮演两个角色面向人的所有权地图让下一个接手的人无论是人类开发者还是 Agent快速知道这个功能由谁拥有、从哪里进入、状态放在哪里。面向 AI Agent 的上下文入口Agent 在扩展该功能前先读 README避免把新逻辑塞回已经过大的组件。原文给出了两条命名约定优先使用README.md而非FEATURE.md以匹配仓库既有的web/src/features/*目录约定仅当目录中已经存在面向用户或由工具生成的 README 时才改用FEATURE.md避免冲突。同时原文强调README 不是变更日志changelog。它应描述持久的边界durable boundaries并指向更深入的迁移笔记而不是逐条记录每次提交改了什么。在仓库中可以找到多个遵循该约定的实例例如 web/src/features/dashboard/README.md、web/src/features/tracing-tables/README.md、web/src/features/chart-view-prototype/README.md 以及 web/src/components/table/peek/README.md。这份规范本身属于 frontend-large-feature-architecture 技能包的一部分在 SKILL.md 中有一条明确要求大型功能目录应包含一份简洁的 README.md 所有权地图。必填章节一份合格 Feature README 的八个组成部分原文规定大型功能的 README 必须包含以下八个章节每个章节回答一个明确的架构问题章节回答的问题Surface功能面该目录拥有哪一块产品界面Entry Points入口挂载该功能的路由文件或父组件以及它们调用的页面/视图生命周期所有者文件Structure目录结构每个子目录负责什么External Consumers外部消费者有哪些其他功能导入了这些组件State Ownership状态所有权服务端/查询状态、路由状态、本地功能状态、全局产品状态、DOM 集成状态、只读 props 分别存放在哪里Performance And Stability Boundaries性能与稳定性边界哪些交互是高频率或外部不稳定的哪些组件允许因此重渲染或测量Migration State迁移状态已改进了什么、哪些状态/动作仍然分散、下一到两个原子化切片是什么Development Context开发上下文扩展该功能前应阅读的 Agent 技能、迁移笔记或 issue 文档以 web/src/features/dashboard/README.md 为例它的结构完全对齐这八个章节Surface项目 Home 页只读 dashboard 查看器、自助 dashboard 详情页以及以preset 放置位渲染的旧版 Home 卡片Entry Pointsweb/src/pages/project/[projectId]/index.tsxHome控制器在挂载前解析 v3/v4 读取路径后渲染HomeDashboard与web/src/pages/project/[projectId]/dashboards/[dashboardId]/index.tsxdashboard 详情两个页面都创建 per-mount 调度器 store 并通过DashboardQuerySchedulerProvider提供Structurecomponents/放旧版 Home 卡片与 dashboard 范围内的对话框/选择器卡片必须从 preset context 接收metricsVersion绝不自己读 sessionhooks/放useDashboardQueryScheduler.tsx调度控制器 hookstores/放 dashboardQuerySchedulerStore.ts per-mount 状态server/放 tRPC routerlib/、utils/放纯辅助函数External Consumers明确指出web/src/features/widgets/拥有DashboardGrid/DashboardWidget/WidgetContent与图表库web/src/hooks/useSSEDashboardQuery.ts拥有 SSE 传输因parseSSEBuffer有非 dashboard 消费者而留在那里。Structure 章节的两个关键约束原文对目录结构提出了具体约定根级components/只放跨功能面复用的组件surface 子目录如detail/用于放置页面控制器、本地 store、actions/、集成 hooks 以及 surface 私有的容器组件。这意味着目录结构本身就在表达边界可复用的放根级页面私有的沉入 surface 目录工作流逻辑集中在actions/。这一约定与 local-feature-state.md 中的复杂工作流放入actions/*.ts或 store actions一脉相承。External Consumers 的价值外部消费者章节让共享导出保持上下文无关context-free并防止意外的 Provider 耦合。例如 web/src/features/tracing-tables/README.md 特别说明共享组件DataTable和TableSelectionManager绝不消费feature 作用域的 context而是通过selectionStoreprop 显式接收 storeweb/src/components/table/table-selection-store.ts因此嵌套表格如 observation peek 中的 ScoresTable不会受外层影响。这正是记录外部消费者这一章节防止耦合的实战体现。状态所有权规则以基线为起点命名每类状态的位置原文的 State Ownership 章节并不要求 README 重新发明状态模型而是要求使用big-feature-rules.md中的所有权基线。README 只需命名每类状态在该功能中的存放位置以及已知的分散状态残留。所有权基线的完整定义见 big-feature-rules.md其核心分工为页面/视图拥有生命周期并创建 feature 作用域的依赖服务端/查询状态留在 tRPC/React Query路由状态留在 router/filter hooks高频本地 UI 状态放在 per-mount 的本地 feature store全局 store只用于跨路由/跨功能共享的产品状态纯数据准备在渲染前把拉取的数据编译成 UI 数据复杂工作流放在actions/*.ts或 store actionsEffect 是集成边界不是常规的状态推导手段昂贵的行/单元格/条目应保持只读置于窄容器之后。Feature README 需要在这条基线上逐类指明状态落在哪里。看 web/src/features/dashboard/README.md 的 State Ownership 是怎么写的服务端/查询状态React Query。tRPC fetch 与 SSE 流在同一[dashboard.executeQuery, input, retry]缓存键下缓存行数据因此相同 widget 共享一条查询/流传输方式切换可复用已缓存行读取路径v3/v4session 状态由页面控制器解析后以必填readPathprop 下传绝不镜像进 store调度器队列上述 per-mount vanilla storewidget 只订阅items[queryId]?.status runningSSE 进度事件高频刻意不进入查询缓存作为发起流的挂载点上的本地状态路由状态时间范围/过滤器/被 peek 的 dashboard 都在页面的 URL hooks 中。这种写法精确到哪个状态在哪个对象里、谁订阅了哪一字段让后续维护者一眼看清状态边界。支撑细节本地 store 的创建方式状态所有权章节隐含了一个重要实现约定本地 store 实例用惰性useState创建而非useMemo因为 store 是已提交挂载视图的一个实例是状态化基础设施其身份应视为状态。见 useObservationsTableView.ts 的写法const [store] useState(() createObservationsTableStore({ initialSelectAll: selectAll, onSelectAllChange: setSelectAll, }), );同一模式在 web/src/components/table/peek/store/peekPanelStore.ts 中再次出现per-mount vanilla Zustand store 只拥有 widget 宽度与瞬时拖拽状态widthFraction/draftFraction/draftExpanded/isResizing所有变更都通过命名 actionsetResizing、cancelResize、setDraftFraction、setDraftExpanded、commitWidth、nudgeWidth完成而是否展开expanded这一可分享、可回退的状态则放在 URLpeekViewexpanded不进 store。性能与稳定性地图给高频交互划定重渲染边界原文要求每个大型功能 README 都要点名必须保持窄幅的高频交互并给出典型清单滚动与虚拟化更新行选中、悬停、展开与懒加载过滤器、已保存视图与列状态变更抽屉drawer、peek 导航与键盘导航浏览器翻译或其他第三方 DOM 变更尺寸调整与动态行测量对每一种交互README 应指明哪一边界应当更新。页面组件不得因为无关状态变更而重新执行昂贵的数据准备、重建列/配置对象或重渲染未变化的昂贵单元格。仓库中 web/src/features/dashboard/README.md 的 Performance And Stability Boundaries 章节给出了教科书式的写法调度器槽位变更只重渲染槽位变化的那个 widget——绝不重渲染整页该 store 取代了页面级useState版本计数器后者曾在每次队列跳变时重渲染整个网格进度事件按 ClickHouse 的进度节奏只重渲染一个 widget 的加载态绝不允许进入查询缓存或 context 值调度器 reset 键必须只包含影响查询的参数绝不含 widget 集合由useDashboardQueryScheduler.clienttest.ts钉死。这套地图直接呼应了把渲染与逻辑分离的总原则高频交互的状态被收敛到 per-mount store 窄选择器订阅页面只在其正真依赖的语义状态变化时才醒来。在 peek 场景中peekPanelStore.ts 的选择器被刻意设计为返回原始值如selectWidgetWidth返回50vw这样的原始 CSS 字符串使订阅在渲染宽度未变化时直接 bail out。现状诚实正在迁移中的功能就如实说明原文明确要求如果一个功能处于迁移中途请如实说明。README 应当把期望边界讲清楚同时把已知的分散状态标注为技术债绝不能把部分迁移的功能包装成最终形态。推荐的风格是**就地更新update-in-place**而非变更日志原文给出了示例骨架Improved in current shape当前形态已改进本地 store 拥有行选中导出 action 已移到actions/exportFeatureData.ts行视图不再订阅过滤器状态。Still spread仍然分散已保存视图状态仍留在页面控制器过滤器选项准备仍是内联的变更工作流仍闭包捕获页面 hooks。Next slice下一个切片把过滤器选项准备抽取为纯辅助函数把批量 action 工作流移入 action 文件把路由/查询胶水与视图组件拆分。这一做法的价值在于每次改进都可评审同时迁移计划保持可见。原文特别强调不要等一次完美重组后才开始记录当前状态。仓库中的两个 README 是这一原则的直接体现web/src/features/tracing-tables/README.md 的 Status / Remaining Spread 章节直言ObservationsTableweb/src/components/table/use-cases/observations.tsx仍是一个控制器组件内联列构建、多 hook 拼装查询状态、渲染期数据准备。按 2026-06 的决策旧版 observations 页面被冻结仅修 bug过滤/搜索纵向在 flag 后重建而不是继续迁移。选 store 与本目录产出的 context-freeDataTable选择 API 被重建后的界面复用。web/src/features/dashboard/README.md 的 Migration State 同样诚实Done 列出已完成项读路径控制器拆分、per-mount vanilla store 上的调度器、SSE 行/状态进入 React Query 缓存、per-widget 响应式槽位订阅Still spread 承认 dashboard 详情页仍是单一大型组件草稿定义状态、粘贴/导入处理器、clone-first 对话框状态全部内联Next slice 给出下一个切片——把详情页的粘贴/导入工作流抽取到actions/*.ts。让更新与变更匹配README 是活的但不是日志原文最后给出更新应与实际变更匹配的约束一次状态/action 抽取只新增或更新相关的迁移状态条目一次新功能目录结构调整在把逻辑移入目录之前先写好所有权地图与外部消费者清单。README 的目标是帮助下一个贡献者避免重新落入同一个大型组件而不是论证迁移已经完成。这与 controller-migration.md 中的第 12 步一致——更新 feature README记录本次 PR 改进了什么、期望边界、已知分散状态、下一个抽取目标也与 big-feature-rules.md 第 10 条硬性规则呼应当一次变更改进了功能边界就更新 feature README 或迁移笔记写明改了什么与下一个切片。仓库中的落地实例四种 README 的写法对照Langfuse 仓库中已存在多个风格各异的 Feature README可以对照学习web/src/features/dashboard/README.md—— 最接近完整规范的样板八个章节齐全外加 Reliability Invariants可靠性不变量如 widget 查询在成功/失败/停滞/卸载每个终态路径上都释放调度槽位SSE 端点设置cancel_http_readonly_queries_on_client_close以在浏览器断开时终止服务端查询。它同时示范了关联但在此目录之外的写法——明确指出web/src/features/widgets/与web/src/hooks/useSSEDashboardQuery.ts的归属。web/src/features/tracing-tables/README.md—— 极简风格Owner Map谁拥有observationsTableStore.ts、useObservationsTableView.ts、ObservationsTableStoreProvider.tsx、State Boundaries、Status / Remaining Spread。它示范了迁移未完成也要写 README的场景。web/src/features/chart-view-prototype/README.md—— 原型目录的写法首先标注状态throwaway design prototype, Storybook-only然后给出 owner map 表格每个文件拥有什么、架构说明纯推导、单向数据流、React.memo渲染边界、以及后续接线路径Phase 1 用 tRPCevents.aggregate替换客户端聚合。这示范了原型也要有所有权地图以及README 记录接线计划的用法。web/src/components/table/peek/README.md—— 状态机制详解型围绕 K/J 键盘导航下的表格状态持久化给出PeekTableStateProvider与key{itemId}重挂载的分层架构图、状态何时持久/何时重置的生命周期说明、已知风险同一 peek 中多个表格共享一个PeekTableState对象以及给新表格接入 peek 的逐步实现指南用usePaginationState替代useQueryParams、用useFullTextSearch替代useQueryParam、为useSidebarFilterState显式传stateLocation: peekContext。它示范了 README 如何承载外部消费者必须显式接线这类契约信息。与技能体系的配合README 是架构文档网络的入口Feature README 不是孤立文档它处于 Langfuse 前端架构文档网络的关键位置。SKILL.md 给出了完整的参考文档索引references/big-feature-rules.md所有权基线与十条硬性规则渲染与逻辑分离、组件多数只读、数据单向流动、action 外置、本地 store 优先、惰性useState创建 store、effect 不作常规状态变更等以及迁移现实——traces、observations、experiments、prompts、evals、datasets、session 视图都存在控制器过重的表面仍有数百个用例待修复包括数百个用于推导/同步状态的useEffectreferences/local-feature-state.md本地功能状态模式包含创建 store、独立 action、store 形态推荐 selector-friendly 的不可变普通对象而非原地变更Set/Map、反模式清单与 11 步迁移步骤references/controller-migration.md从控制器组件到受管功能的 14 步迁移路径以及按功能面traces/observations 表、session 详情、实验创建向导、prompt 管理、数据集等推荐的首个切片references/react-without-useeffect.md 与 references/virtualized-lists.md黄金示例与虚拟化列表专项。Feature README 正是这张网络的入口层每个大型功能通过自己的 README 指明扩展本功能前先读哪份技能/笔记把新贡献者导向正确的上下文同时以 Current-State Honesty 把技术债暴露在明面上避免下一代维护者再次踩进同一个巨型组件。【免费下载链接】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),仅供参考
返回列表