Sentry 前端开发规范与实践指南:基于 static/AGENTS.md 的 React 19 + TypeScript 开发手册
2026/9/10 13:53:50 网站建设 项目流程

Sentry 前端开发规范与实践指南:基于 static/AGENTS.md 的 React 19 + TypeScript 开发手册

【免费下载链接】sentryDeveloper-first error tracking and performance monitoring项目地址: https://gitcode.com/GitHub_Trending/sen/sentry

Sentry 的static/目录承载着整个 Web 前端的核心代码。这篇指南以仓库根目录下 static/AGENTS.md 为骨架,系统梳理 Sentry 前端的技术栈选型、工程目录结构、代码风格红线、数据请求范式、React 渲染纯度约束、设计系统用法、测试方法论与 SDK 埋点规范,并结合package.jsonrspack.config.tssrc/sentry/features/temporary.py等源码级证据深入讲解其落地细节。读完这篇指南,你将掌握在 Sentry 这样的大型监控产品前端中组织页面、发起 API 请求、使用设计系统原语、编写测试以及埋点打标签的完整实战方案,也能直接迁移其中的工程实践到自己的 React 项目中。

一、为什么需要这份前端开发指南

Sentry 是一个典型的前后端分离的大型单体仓库:后端是 Django(Python),前端是位于static/目录下的单页应用。正如 static/AGENTS.md 开头所述,这份文档是AI Agent 和前端工程师在static/目录下开发时的唯一事实来源(source of truth),根目录的 AGENTS.md 则提供了跨前后端的通用命令指引。

仓库按职责划分了多个 AGENTS.md,覆盖不同开发领域:

工作范围读取的 AGENTS.md
前端(static/**/*.{ts,tsx,js,jsx,css,scss}static/AGENTS.md
后端(src/**/*.pysrc/AGENTS.md
测试(tests/**/*.pysrc/**/tests/**/*.pytests/AGENTS.md
全局概览与通用命令AGENTS.md

二、前端技术栈全景

static/AGENTS.md 明确列出了 Sentry 前端的核心技术栈,结合 package.json 中的依赖版本可以进一步确认:

  • 语言:TypeScript。规则第 4 条强制“ALWAYS use TypeScript”,项目根目录的 tsconfig.json 定义了严格类型检查配置。
  • 框架:React 19(package.jsonreact: 19.2.3react-dom: 19.2.3)。
  • 构建工具:Rspack(Webpack 的替代品),配置在 rspack.config.ts。package.json中的build脚本即rspack --config ./rspack.config.ts
  • 包管理:pnpm(packageManager: pnpm@10.30.2),使用pnpm-lock.yaml锁定依赖。
  • 状态管理:Reflux + React Query(TanStack Query)。注意这是 Sentry 的过渡期技术状态——Reflux 是历史遗留,新代码明确禁止新增 Reflux store(见下文"代码风格红线")。
  • 样式方案:Emotion(CSS-in-JS)+ Less。CSS-in-JS 用于组件级样式,Less 文件位于 static/less 目录。
  • 测试:Jest + React Testing Library(RTL),见 jest.config.ts。

值得注意的几个"非主流"选型:Oxlint 取代 ESLintoxlint.config.ts+@oxlint系列依赖),Rspack 取代 Webpack@rspack/core@2.2.0),pnpm 取代 npm/yarn。这些都是在工程化上追求性能与规模化的结果。

三、重要文件与目录地图

static/AGENTS.md 给出了前端代码的完整目录约定,这是理解 Sentry 前端组织方式的关键:

职责路径约定
组件static/app/components/{component}/
页面视图static/app/views/{area}/{page}.tsx
状态存储static/app/stores/{store}Store.tsx
Action 创建器static/app/actionCreators/{resource}.tsx
工具函数static/app/utils/{utility}.tsx
类型定义static/app/types/{area}.tsx
API 客户端static/app/api.tsx

从仓库结构看(见 static/app 目录),这套约定被严格执行:components下按功能分子目录(如components/corecomponents/badgecomponents/events),views下按业务域组织页面。

3.1 路由(Routing)

  • 路由统一在 static/app/routes.tsx 定义;
  • 遵循 React Router v6 模式(package.jsonreact-router-dom: 6.30.3);
  • 路由组件尽可能懒加载React.lazy(() => import('...'))。这与 rspack.config.ts 中SHOULD_LAZY_COMPILATION(懒编译入口之外的路由)的构建优化策略一脉相承——懒加载同时作用于运行时React.lazy按需拆包)与编译期(Rspack 懒编译节省内存和启动时间)。

四、前端 API 请求:从 useApiQuery 到 apiOptions 的范式迁移

static/AGENTS.md 的 "Frontend API Calls" 一节规定了一个明确的硬性迁移方向:

使用useQuery+apiOptions发起 API 请求;永远不要使用已废弃的useApiQuery/getApiQueryData/setApiQueryDatastaleTime是必填参数。

虽然useApiQuery在仓库中仍有使用(例如 static/app/components/charts/useSessionsRequest.tsx、static/app/components/events/autofix/useAutofixSetup.tsx),但这些都属于存量代码,新代码一律走apiOptions范式。详细的完整指南(条件请求、调用点泛型、响应头/分页)由frontend-data-fetching技能(.agents/skills/frontend-data-fetching/SKILL.md)承载。

4.1 基本用法

import {skipToken, useQuery} from '@tanstack/react-query'; import {apiOptions} from 'sentry/utils/api/apiOptions'; // 基本用法 const query = useQuery( apiOptions.as<ResponseType>()('/organizations/$organizationIdOrSlug/endpoint/', { path: {organizationIdOrSlug: organization.slug}, staleTime: 30_000, }) ); // 条件请求 —— 将 skipToken 作为 path 传入即可禁用该查询 const query = useQuery( apiOptions.as<ResponseType>()('/organizations/$organizationIdOrSlug/items/$itemId/', { path: itemId ? {organizationIdOrSlug: organization.slug, itemId} : skipToken, staleTime: 30_000, }) );

4.2 关键规则

  1. staleTime必填:必须显式选择一个值——0、毫秒数、Infinity'static'
  2. 围绕apiOptions做抽象,而不是围绕useQuery:返回 options 对象,让调用方自行决定传给useQueryuseQueries还是prefetchQuery
  3. 缓存存的是{json, headers}而非裸 bodyapiOptions默认用select提取.json,但getQueryDatasetQueryDataretry函数与predicate回调收到的都是完整的ApiResponse<T>结构。
  4. 不要在 Query 中使用api.requestPromise:它会返回错误的结构;如需手写queryFn,改用apiFetch

4.3 类型推断:禁止调用点泛型

技能文档强调了一个极易踩坑的点——永远不要在useQueryuseMutationqueryOptionsmutationOptions的调用点传类型参数,让 TypeScript 从queryFn/mutationFn推断:

// ❌ 错误:给 useMutation/useQuery 传泛型 useMutation<ResponseType, RequestError, Variables, Context>({...}) // ✅ 正确:标注 mutationFn,让类型从函数签名推断 useMutation({ mutationFn: (variables: MyVariables) => fetchMutation<MyResponse>({...}), })

具体规则:类型化mutationFn的参数而不是 hook 泛型;用fetchMutation<T>标注返回值;错误类型不要显式写成RequestError(这本质上是类型断言),用if (error instanceof RequestError)做运行时收窄;不要显式声明 context 类型,让它从onMutate的返回值推断。

五、General Frontend Rules:五条红线

static/AGENTS.md 定义了五条不可逾越的前端规则,它们共同决定了 Sentry 前端代码的形态:

  1. 禁止新增 Reflux store:Reflux 属于历史遗留,状态管理的新代码一律使用 TanStack Query(服务端状态)+ React 内置状态/其他方案(客户端状态)。
  2. 禁止类组件:全部使用函数组件 + Hooks,这也与 React 19 的时代背景一致。
  3. 禁止 CSS 文件:优先使用 core 组件([static/app/components/core](https://link.gitcode.com/i/de705a0aecd4ddedc06911ea0859218e)),仅在真正边缘的情况下使用 Emotion。
  4. 必须使用 TypeScript:无类型代码不允许进入代码库。
  5. 测试必须与源码同目录(colocate)*.spec.tsx紧邻被测组件,例如 static/app/components/core/datetime.spec.tsx 紧挨着datetime.tsx
  6. 路由懒加载React.lazy(() => import('...'))

这些规则的价值在于可预见性:任何工程师或 Agent 打开一个不熟悉的目录,都能根据目录约定和代码形态快速定位组件、视图、store 与测试。

六、Refs 使用纪律:渲染必须纯净

static/AGENTS.md 的 "Refs" 一节给出了一个非常具体的 React 陷阱——渲染期间读写ref.current会破坏 React 的渲染纯净性:render 必须是纯函数,而 ref 是 React 不追踪的可变状态。渲染期读 ref 可能在并发渲染下拿到过期值,写 ref 则制造了副作用、让 render 变得不纯。

正确姿势:只在 effect(useEffect/useLayoutEffect)或事件处理器/回调里读写ref.current;渲染期需要值就从 props/state 派生const,或提升到useState/useMemo;只有"必须跨渲染持久且不触发重渲染"的值(DOM 节点、定时器、供 effect 后续读取的 previous-value 跟踪)才值得用 ref。

// ❌ 渲染期间读写 ref —— 副作用 + 并发渲染下的过期值 function Component({value}: Props) { renderCountRef.current += 1; // 渲染期副作用 const previous = prevValueRef.current; // 并发渲染下可能过期 prevValueRef.current = value; // 渲染期写入 return <div>{previous}</div>; } // ✅ 在 effect 中改 ref,渲染值靠派生 function Component({value}: Props) { const prevValueRef = useRef(value); useEffect(() => { prevValueRef.current = value; // 在 effect 中写入 }, [value]); return <div>{value}</div>; }

七、UI Patterns 与 Design System

7.1 剪贴板复制模式

当需要实现"高级复制到剪贴板"功能(如复制 Markdown、JSON 等不同格式)时,不要为每种格式各做一个按钮,而应使用sentry/components/copyAsDropdown(源码位于 static/app/components/copyAsDropdown.tsx),在一个下拉菜单中提供不同格式选项。这统一了交互模式,避免每个页面自造轮子。

7.2 设计系统:从 @sentry/scraps 取原语

Sentry 的设计系统核心是@sentry/scraps包——优先使用它的核心原语,而不是手写 styled components 来做布局和排版。完整参数/token 参考见design-system技能(.agents/skills/design-system/SKILL.md)。关键约束如下:

  • 布局:用FlexGridStackContainer,禁止手写display: flex/grid
  • 排版:用TextHeading,禁止裸用<p><span><div><h1><h6>
  • 优先组件 props 而非style属性:用gap/padding 而不是margin
  • 用响应式 props 替代媒体查询:例如{xs: 'column', md: 'row'}表示在移动端纵排、中等宽度以上横排。
  • 布局与排版分离Flex/Grid负责布局,Text/Heading负责排版,不要耦合在同一个 styled component 里。
  • 优先InfoTip/InfoText而非裸Tooltip
  • 新组件要附带*.stories.mdxstory
  • 优先 core 组件(static/app/components/core 下已有alertbuttonavatarbadgecheckboxdisclosureforminputmodaltabstabletexttooltip等数十个原语),Emotion 只留给真正的边缘场景。

7.3 其他核心组件约定

  • 头像:用static/app/components/core/avatar下的<UserAvatar/>/<TeamAvatar/>/<ProjectAvatar/>等(列表用<AvatarList>),禁止裸<img>
  • 折叠/展开:用核心<Disclosure>组件,不要自己手写 expand/collapse。
  • 图标:从sentry/icons导入,图标文件放在static/app/icons(入口见 static/app/icons/index.tsx),禁止内联 SVG;用 svgo/svgomg 优化。
  • 图片:通过sentry-images别名(webpack loader)导入,图片放在static/app/images,禁止用静态路径引用。

八、React 测试:RTL 与 MockApiClient

前端测试(*.spec.tsx、React Testing Library、MockApiClient、路由/网络测试)的完整方法论由react-testing技能承载(.agents/skills/react-testing/SKILL.md),涵盖查询优先级、禁止 mock hook、fixtures 用法、异步断言、网络请求 mock 等主题。

工程层面的测试入口在 package.json:pnpm test-ci <file_path>运行指定文件(例如pnpm test-ci components/avatar.spec.tsx),pnpm test为带--watch的开发模式。测试文件与源码同目录存放,这是上面"五条红线"之一。

九、Sentry SDK 埋点:遵循 OTel/Sentry 约定命名

Sentry.setTag/setContext或 span 的setAttribute之前,先检查@sentry/conventions是否已有标准命名。复用约定名能保证属性可查询、且与其他生产者(SDK、Relay)对同一概念发出的数据一致——自定义名字会把同一份数据割裂到两个 key 上。这条规则与后端技能backend-conventions中的 Python 侧规则保持同步,因为前端 span 和后端 span 可能描述同一次请求

注意:单个名称常量(如USER_AGENT_ORIGINAL)位于/attributes子路径下,而不是包根路径;包根只重新导出元数据表——ATTRIBUTE_METADATA(每个属性的完整记录:简介、类型、别名、废弃状态)和ATTRIBUTE_SEARCH_METADATA(搜索字段 UI 渲染的描述,见 static/app/utils/fields)。

import {USER_AGENT_ORIGINAL} from '@sentry/conventions/attributes'; // 错误:给一个 conventions 已覆盖的概念发明新名字 span.setAttribute('request_user_agent', navigator.userAgent); // 正确:使用既有约定名 span.setAttribute(USER_AGENT_ORIGINAL, navigator.userAgent);

新增候选命名前,先 grepnode_modules/@sentry/conventions/dist/attributes.d.ts确认是否存在。这些约定由 OTel 语义约定加上 Sentry 自身的模型生成。

十、前后端联动的两条协作规则

10.1 Feature Flags(FlagPole)

Sentry 用 FlagPole 管理功能开关(src/sentry/features 目录,配置见 src/sentry/features/temporary.py)。新功能必须藏在 flag 后面:在temporary.py中注册,Python 侧用features.has(...)检查,前端用organization.features.includes(...)检查。完整的注册/api_expose/测试/灰度流程见feature-flags技能(.agents/skills/feature-flags/SKILL.md)。

temporary.py源码可以看到 flag 注册的三种作用域与策略组合:

作用域策略示例
SystemFeatureINTERNALorganizations:create(默认开启)
OrganizationFeatureFLAGPOLEorganizations:ai-issue-detectionorganizations:authv2-rollout
ProjectFeatureFLAGPOLE项目级灰度功能

值得注意的细节:temporary.py的 docstring 明确警告这些 flag只用于门控新开发功能,且注定要被移除("CLEAN UP YOUR FEATURE FLAGS!"),因为遗留 flag 会引入长期理解的复杂度。删除已完成的 flag 或 option 有固定的 PR 顺序,需使用remove-option-or-flag技能。

10.2 前后端分离部署

前端(static/)与后端(src/tests/不是原子化部署的,CI 会强制检查:

  • 同时改动前后端时必须拆成两个独立 PR
  • 前端依赖新的 API 时,先合入后端 PR
  • 纯测试新增与src/改动放在同一个 PR 是允许的。

十一、常用开发命令速查

虽然 static/AGENTS.md 主要聚焦代码规范,其引用的根目录 AGENTS.md 给出了前端日常命令,整理如下:

# 开发环境 pnpm run dev # 完整 dev server(需要先 devservices up) pnpm run dev-ui # 仅前端 + 热重载,API 代理到生产 sentry.io # 类型检查(检查整个项目,不接受文件路径参数;不要直接用 tsc) pnpm run typecheck # Lint / 自动修复 pnpm run lint:js # 全部 JS/TS pnpm run lint:js components/avatar.tsx # 指定文件 pnpm run fix # 自动修复 # 测试 pnpm test-ci <file_path> # 运行测试 pnpm test-ci components/avatar.spec.tsx # 指定文件

对应的环境准备:SENTRY_DEVENV_FRONTEND_ONLY=1 devenv sync(跳过迁移,推荐用于纯前端/pytest 场景)、direnv allowdevservices up。前端构建配置 rspack.config.ts 中还支持SENTRY_UI_HOT_RELOADENABLE_TS_CHECKER(类型检查资源开销大,需显式开启)、LAZY_COMPILATION(懒编译,节省内存和启动时间)、USE_TANSTACK_DEVTOOL等环境开关。

十二、总结:一份可迁移的前端工程实践

回顾 static/AGENTS.md 的全部内容,它本质上是 Sentry 前端团队多年工程经验的浓缩,其可迁移价值在于:

  1. 显式技术栈 + 目录约定:让千人大仓保持可导航性;
  2. "禁止"清单文化:禁 Reflux、禁类组件、禁 CSS 文件、禁渲染期读写 ref、禁调用点泛型——每条禁令背后都是一个真实的线上教训;
  3. 把复杂决策委托给技能(skills):数据请求、测试、设计系统、特性开关等主题都有独立技能文档承载完整方法论,AGENTS.md 保持精简、可扫描;
  4. 前后端规范对齐:埋点命名约定在前后端保持同步,保证同一请求的两端数据可关联查询。

对于正在构建大型 React 应用的团队,这份文档提供了一个经过生产验证的参照系:如何用文档约束 Agent 与工程师、如何用目录和红线维持代码一致性、如何用约定名保持遥测数据的可查询性。

【免费下载链接】sentryDeveloper-first error tracking and performance monitoring项目地址: https://gitcode.com/GitHub_Trending/sen/sentry

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询