
Comp AI CRM 中的 Vercel React Best Practices面向 AI Agent 的 React/Next.js 性能优化规则集深度解析【免费下载链接】crmComp AI CRM is an open source, CRM designed for AI agents. Agentic-first CRM.项目地址: https://gitcode.com/gh_mirrors/crm48/crmComp AI CRM 是一个面向 AI Agent 设计的开源 CRMAgentic-first CRM其 Web 前端基于 React 与 Next.js 构建并内置了一套来自 Vercel 工程团队、专为 Agent 和 LLM 优化而设计的性能规则集——.agents/skills/vercel-react-best-practices。本篇文章以该规则集的 README 与编译产物AGENTS.md为主体系统讲解它的目录结构、构建管线、8 大分类共 70 条规则的组织方式与核心代码范式并结合 Comp AI CRM 仓库内的真实组件验证这些最佳实践的实际落地。读完本文你将掌握一套可复用的 React/Next.js 性能审计清单以及如何以规则文件 → 编译产物 → 测试用例的方式维护自己的 Agent 可读工程规范。技能包是什么为 Agent 与 LLM 打造的规则化性能指南.agents/skills/vercel-react-best-practices/README.md定义了一个结构化仓库structured repository用于创建和维护一套针对 Agent 与 LLM 优化过的 React 最佳实践。与面向人类读者的普通文档不同这套规则集的设计目标是让 AI 助手在编写、审查、重构 React/Next.js 代码时能够稳定、一致地遵循统一范式。其SKILL.md元数据将其定位为一个可被触发的技能skillThis skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.技能的元信息记录在 .agents/skills/vercel-react-best-practices/SKILL.mdname 为vercel-react-best-practiceslicense 为 MITauthor 为 vercelversion 1.0.0metadata.json 则记录了版本 1.0.0、归属组织 Vercel Engineering、日期 2026 年 1 月以及摘要。根据这些元数据本技能包的适用时机包括编写新的 React 组件或 Next.js 页面实现客户端或服务端数据获取审查代码中的性能问题重构现有 React/Next.js 代码优化打包体积与加载时间。仓库结构一份规则即代码的工程布局README 给出了该技能包的整体结构整个目录位于仓库的 .agents/skills/vercel-react-best-practices/ 下路径作用rules/存放单条规则文件one rule per filerules/_sections.mdSection 元数据标题、影响级别、描述rules/_template.md创建新规则时使用的模板rules/area-description.md具体的规则文件如async-parallel.mdsrc/构建脚本与工具metadata.json文档元数据版本、组织、摘要AGENTS.md编译产物全部规则汇总generatedtest-cases.json用于 LLM 评估的测试用例generated其中两个核心文件值得关注rules/_sections.md定义了全部 8 个 Section 的排序、影响级别与描述rules/_template.md是每条新规则的骨架。而AGENTS.md3810 行是构建脚本把 70 条规则编译合并后的完整产物也就是 Agent 实际消费的总手册test-cases.json则是从规则中抽取的正反例测试用例用于对 LLM 进行评测。快速上手从安装到构建的完整管线README 的 Getting Started 给出了四个命令构成了这套规则集的核心工作流# 1. 安装依赖 pnpm install # 2. 从规则文件编译生成 AGENTS.md pnpm build # 3. 校验规则文件 pnpm validate # 4. 抽取测试用例供 LLM 评测 pnpm extract-tests配套的脚本还有pnpm dev构建并校验build validate 的组合。整个工作流的设计理念是规则文件是唯一的事实来源source of truthAGENTS.md与test-cases.json均为生成物不应手工编辑。修改规则后必须重新运行pnpm build让产物保持同步。规则的目录体系8 大分类与优先级规则按性能影响优先级被划分为 8 个分类Section每个分类对应一个文件名前缀。这张优先级表来自 SKILL.md 与 rules/_sections.md是理解整套规则编排的关键优先级分类影响级别文件名前缀1Eliminating Waterfalls消除瀑布请求CRITICALasync-2Bundle Size Optimization打包体积优化CRITICALbundle-3Server-Side Performance服务端性能HIGHserver-4Client-Side Data Fetching客户端数据获取MEDIUM-HIGHclient-5Re-render Optimization重渲染优化MEDIUMrerender-6Rendering Performance渲染性能MEDIUMrendering-7JavaScript PerformanceJS 微优化LOW-MEDIUMjs-8Advanced Patterns高级模式LOWadvanced-各 Section 的官方定位来自_sections.mdEliminating Waterfalls瀑布是性能的头号杀手每个串行await都会叠加一次完整的网络延迟消除它们收益最大Bundle Size Optimization减小初始 bundle 体积可直接改善 Time to InteractiveTTI与 Largest Contentful PaintLCPServer-Side Performance优化服务端渲染与数据获取消除服务端瀑布并降低响应时间Client-Side Data Fetching自动去重与高效取数模式减少冗余网络请求Re-render Optimization减少不必要的重渲染最小化浪费的计算提升 UI 响应性Rendering Performance优化渲染过程减少浏览器需要做的工作JavaScript Performance对热点路径的微优化积少成多Advanced Patterns针对特定场景、需要谨慎实现的高级模式。文件名命名约定与自动编号README 明确了规则文件的命名约定以_开头的文件是特殊文件如_sections.md、_template.md不参与构建规则文件名为area-description.md形式例如async-parallel.mdSection 通过文件名前缀自动推断async-、bundle-、server-、client-、rerender-、rendering-、js-、advanced-每个 Section 内部的规则按标题字母序自动排序ID如 1.1、1.2由构建过程自动生成因此维护者无需手工管理编号。这也解释了为什么在编译产物 AGENTS.md 中每条规则都带上了如1.1、2.1这样的自动编号共 8 大节、70 条规则。影响级别Impact Levels每条规则通过 frontmatter 中的impact字段声明影响级别形成从高到低的完整梯度CRITICAL最高优先级带来主要性能收益HIGH显著性能改进MEDIUM-HIGH中高收益MEDIUM中等性能改进LOW-MEDIUM中低收益LOW渐进式改进。规则文件结构可被机器解析的模板README 规定每条规则文件都必须遵循 rules/_template.md 给出的结构——YAML frontmatter 提供机器可读元数据正文则统一使用 Incorrect/Correct 正反对照的示例格式--- title: Rule Title Here impact: MEDIUM impactDescription: Optional description tags: tag1, tag2, tag3 --- ## Rule Title Here Brief explanation of the rule and why it matters. **Incorrect (description of whats wrong):** typescript // Bad code exampleCorrect (description of whats right):// Good code exampleOptional explanatory text after examples.Reference: Link to documentation or resourcefrontmatter 字段说明 - title规则标题 - impact影响级别取值见上文 6 档 - impactDescription可选的影响描述例如 20-50% improvement、2-10× improvement - tags逗号分隔的标签如 async, parallelization, promises, waterfalls。 正文要求清晰的正反例 解释例如 [rules/async-parallel.md](https://link.gitcode.com/i/47c393cc39b449bc49e5f0a0e6867fcd) 用三行串行 await 与 Promise.all() 并行取数作对照[rules/bundle-barrel-imports.md](https://link.gitcode.com/i/9593fff2df2f78a7f5f1a444ecbc6037) 则对比了整库导入与深路径/optimizePackageImports 两种写法。这种结构让 Agent 可以直接把规则当作 lint 规则理解也方便抽取成评测用例。 ## 8 大分类 70 条规则全景 以下是 [SKILL.md](https://link.gitcode.com/i/c4e5f3b7a2109ec95428f4120f8853d3) Quick Reference 列出的全部 70 条规则清单结合编译产物 AGENTS.md 的章节编号 ### 1. Eliminating WaterfallsCRITICALasync- 1.1 async-cheap-condition-before-await — 在 await 异步标志/远程值之前先检查廉价的同步条件 1.2 async-defer-await — 把 await 移入真正使用它的分支 1.3 async-dependencies — 对部分依赖场景使用 better-all 最大化并行度 1.4 async-api-routes — 在 API 路由中尽早启动 Promise、延后 await 1.5 async-parallel — 对相互独立的操作使用 Promise.all() 1.6 async-suspense-boundaries — 用 Suspense 边界流式渲染内容。 ### 2. Bundle Size OptimizationCRITICALbundle- 2.1 bundle-barrel-imports — 直接按源文件导入避免 barrel 文件 2.2 bundle-analyzable-paths — 优先使用可静态分析的导入路径与文件系统路径 2.3 bundle-dynamic-imports — 对重型组件使用 next/dynamic 2.4 bundle-defer-third-party — 在水合之后再加载分析与日志类三方库 2.5 bundle-conditional — 仅在功能启用时加载对应模块 2.6 bundle-preload — 在 hover/focus 时预加载以获得感知速度。 ### 3. Server-Side PerformanceHIGHserver- 3.1 server-auth-actions — Server Actions 要像 API 路由一样做认证 3.2 server-cache-react — 使用 React.cache() 做单请求内去重 3.3 server-cache-lru — 跨请求缓存使用 LRU 缓存 3.4 server-dedup-props — 避免 RSC props 中重复序列化 3.5 server-hoist-static-io — 将静态 I/O字体、Logo提升到模块级 3.6 server-no-shared-module-state — 避免在 RSC/SSR 中使用模块级可变请求状态 3.7 server-serialization — 最小化传给客户端组件的数据 3.8 server-parallel-fetching — 通过组件组合重构以并行化取数 3.9 server-parallel-nested-fetching — 在 Promise.all 内链式处理逐项嵌套取数 3.10 server-after-nonblocking — 用 after() 调度非阻塞操作。 ### 4. Client-Side Data FetchingMEDIUM-HIGHclient- 4.1 client-swr-dedup — 用 SWR 做自动请求去重 4.2 client-event-listeners — 去重全局事件监听器 4.3 client-passive-event-listeners — 滚动类监听使用 passive 模式 4.4 client-localstorage-schema — 版本化并最小化 localStorage 数据。 ### 5. Re-render OptimizationMEDIUMrerender- 5.1 rerender-derived-state-no-effect — 在渲染期间派生状态而不是用 effect 5.2 rerender-defer-reads — 不要订阅只在回调里用到的状态 5.3 rerender-simple-expression-in-memo — 简单原始值表达式不要包 useMemo 5.4 rerender-no-inline-components — 不要在组件内部定义组件 5.5 rerender-memo-with-default-value — 将 memo 组件的非原始默认参数提取为常量 5.6 rerender-memo — 把昂贵工作提取为 memo 化组件 5.7 rerender-dependencies — effect 依赖使用原始值而非对象 5.8 rerender-move-effect-to-event — 把交互逻辑放进事件处理器 5.9 rerender-split-combined-hooks — 拆分依赖独立的组合 hook 5.10 rerender-derived-state — 订阅派生布尔值而非连续原始值 5.11 rerender-functional-setstate — 使用函数式 setState 获得稳定回调 5.12 rerender-lazy-state-init — 昂贵初始值用函数形式传给 useState 5.13 rerender-transitions — 非紧急更新使用 startTransition 5.14 rerender-use-deferred-value — 用 useDeferredValue 延后昂贵渲染以保持输入响应 5.15 rerender-use-ref-transient-values — 高频瞬时值用 ref 存储。 ### 6. Rendering PerformanceMEDIUMrendering- 6.1 rendering-animate-svg-wrapper — 动画作用于 div 包裹层而非 SVG 元素本身 6.2 rendering-content-visibility — 长列表使用 content-visibility 6.3 rendering-hoist-jsx — 将静态 JSX 提取到组件外部 6.4 rendering-svg-precision — 降低 SVG 坐标精度 6.5 rendering-hydration-no-flicker — 用内联脚本处理客户端独有数据以避免闪烁 6.6 rendering-hydration-suppress-warning — 抑制预期的水合不一致警告 6.7 rendering-activity — 使用 Activity 组件做显示/隐藏 6.8 rendering-conditional-render — 条件渲染用三元表达式而非 6.9 rendering-usetransition-loading — 优先用 useTransition 管理加载状态 6.10 rendering-resource-hints — 使用 React DOM 资源提示 API 做预加载 6.11 rendering-script-defer-async — script 标签使用 defer 或 async。 ### 7. JavaScript PerformanceLOW-MEDIUMjs- 7.1 js-batch-dom-css — 通过 class 或 cssText 批量修改 CSS 7.2 js-index-maps — 重复查找先构建 Map 索引 7.3 js-cache-property-access — 循环中缓存对象属性访问 7.4 js-cache-function-results — 在模块级 Map 中缓存函数结果 7.5 js-cache-storage — 缓存 localStorage/sessionStorage 读取 7.6 js-combine-iterations — 把多个 filter/map 合并为一次循环 7.7 js-length-check-first — 昂贵比较前先检查数组长度 7.8 js-early-exit — 函数尽早 return 7.9 js-hoist-regexp — 把 RegExp 创建移出循环 7.10 js-min-max-loop — 求最小/最大用循环而非排序 7.11 js-set-map-lookups — 用 Set/Map 做 O(1) 查找 7.12 js-tosorted-immutable — 用 toSorted() 保持不可变 7.13 js-flatmap-filter — 用 flatMap 一次遍历完成 mapfilter 7.14 js-request-idle-callback — 把非关键工作推迟到浏览器空闲时段。 ### 8. Advanced PatternsLOWadvanced- 8.1 advanced-effect-event-deps — 不要把 useEffectEvent 的结果放进 effect 依赖 8.2 advanced-event-handler-refs — 把事件处理器存入 ref 8.3 advanced-init-once — 应用级初始化只执行一次而非每次挂载 8.4 advanced-use-latest — 用稳定回调引用模式useEffectEvent/ref获取最新值。 ## 核心规则纵深解读附源码级示例 下面从编译产物 [AGENTS.md](https://link.gitcode.com/i/0f48d47a033c0fbe7c245412531955ba) 中选取几个代表性规则深入讲解其原理与代码范式。 ### 消除瀑布Promise.all 与早启动 瀑布waterfall是头号性能杀手。规则 1.5Promise.all是最基础的一条——三个相互独立的请求串行 await 需要 3 个往返 typescript // Incorrect: sequential execution, 3 round trips const user await fetchUser() const posts await fetchPosts() const comments await fetchComments() // Correct: parallel execution, 1 round trip const [user, posts, comments] await Promise.all([ fetchUser(), fetchPosts(), fetchComments() ])规则 1.4API 路由进一步要求尽早启动、延后 await。错误写法中config要等authdata要等两者正确写法在函数开头同时启动auth()与fetchConfig()两个 Promise随后合并等待export async function GET(request: Request) { const sessionPromise auth() const configPromise fetchConfig() const session await sessionPromise const [config, data] await Promise.all([ configPromise, fetchData(session.user.id) ]) return Response.json({ data, config }) }规则 1.6Suspense 边界则建议不要在异步组件里await后再返回 JSX而是把取数收敛到Suspense包裹的叶子组件中让 Sidebar/Header/Footer 立即渲染、数据流式到达多个组件还可以共享同一个 Promise配合use()解包既保证只发起一次请求又避免布局阻塞。打包体积避免 barrel 文件规则 2.1barrel imports指出像lucide-react这样的图标库入口文件可能包含多达 10,000 个 re-export直接import { Check } from lucide-react会加载 1,583 个模块、带来 200-800ms 的运行时导入成本冷启动场景。为什么 tree-shaking 帮不上忙因为库被标记为 external不打进 bundle时打包器无法优化它而若打进 bundle 以启用 tree-shaking构建又会因为分析整个模块图而显著变慢。该规则给出的正确姿势分两种在 Next.js 13.5 中使用optimizePackageImports配置让框架自动改写为直接导入保留 TypeScript 类型与编辑器补全或在非 Next.js 项目中改为深路径导入如import Button from mui/material/Button。同时规则也提醒了一个 TypeScript 陷阱lucide-react的深路径没有.d.ts文件直接导入会退化为隐式any在strict/noImplicitAny下报错——因此优先optimizePackageImports或先确认库为其子路径导出了类型。值得注意Comp AI CRM 仓库本身就大量使用按包内路径导入的方式。例如 apps/app/app/(app)/[slug]/sales-dashboard.tsx 中import { Card, CardDescription, CardHeader, CardTitle } from crm/ui/components/card; import { DashboardRow, StatGroup } from crm/ui/components/dashboard; import { AreaTrend, DonutStat } from /components/dashboard-charts;可以看到项目直接从crm/ui/components/card、crm/ui/components/dashboard等子路径导入而不是从crm/ui的 barrel 入口一次性引入全部组件——正是规则 2.1 的工程实践。规则 2.3重型组件动态导入的仓库佐证同样明确。apps/app/components/dashboard-charts.tsx 中图表组件用next/dynamic延迟加载并显式设置ssr: false与加载占位import dynamic from next/dynamic; const load () import(crm/ui/components/dashboard-chart); const loading () (/* skeleton 占位 */); export const AreaTrend dynamic(() load().then((m) m.AreaTrend), { ssr: false, loading, }); export const DonutStat dynamic(() load().then((m) m.DonutStat), { ssr: false, loading, });这对应规则 2.3bundle-dynamic-imports重型组件不进主 chunk与规则 2.5bundle-analyzable-paths把模块路径收拢到字面量crm/ui/components/dashboard-chart保持静态可分析的典型落地。服务端性能模块级静态 I/O 与跨请求缓存规则 3.5hoist static I/O针对next/og生成图片、读取字体/Logo 这类场景在路由处理器内部每次请求都fetch字体文件是巨大浪费。正确做法是把 I/O 提升到模块级让 Promise 在模块首次导入时就开始// Module-level: runs ONCE when module is first imported const fontData fetch( new URL(./fonts/Inter.ttf, import.meta.url) ).then(res res.arrayBuffer()) export async function GET(request: Request) { const [font] await Promise.all([fontData]) return new ImageResponse(/* ... */, { fonts: [{ name: Inter, data: font }] }) }规则 3.3LRU 缓存指出React.cache()只在单请求内生效跨请求共享例如用户先点按钮 A 再点按钮 B两次都要同一份用户数据应使用 LRU 缓存max: 1000ttl: 5 * 60 * 10005 分钟是一个常用配置。规则 3.2React.cache()则提醒其按Object.is浅比较参数判缓存命中因此内联对象每次都是新引用、永远缓存未命中——应复用同一对象引用。规则 3.6RSC 边界序列化强调Server/Client 边界会把对象所有属性序列化为字符串并嵌入 HTML 与后续 RSC 请求页面重量直接受影响。客户端只用 1 个字段就不要传整个 50 字段对象// Incorrect: serializes all 50 fields async function Page() { const user await fetchUser() // 50 fields return Profile user{user} / } // Correct: serializes only 1 field async function Page() { const user await fetchUser() return Profile name{user.name} / }重渲染优化派生状态与函数式 setState规则 5.1派生状态是 React 官方你可能不需要 effect哲学的浓缩能从当前 props/state 计算出的值就不要放进 state 再靠 effect 同步// Incorrect: redundant state and effect const [fullName, setFullName] useState() useEffect(() { setFullName(firstName lastName) }, [firstName, lastName]) // Correct: derive during render const fullName firstName lastName规则 5.11函数式 setState强调基于当前状态更新时使用函数式形式从而获得稳定回调引用、消除陈旧闭包// Incorrect: callback depends on items, recreated on every items change const addItems useCallback((newItems: Item[]) { setItems([...items, ...newItems]) }, [items]) // Correct: stable callback, never recreated const addItems useCallback((newItems: Item[]) { setItems(curr [...curr, ...newItems]) }, [])规则 5.4不要在组件内定义组件解释了每次渲染都创建新组件类型 → React 全量卸载重挂 → 输入框失焦、动画重启、effect 反复执行这一经典 bug并主张通过 props 传递而非闭包共享父级变量。渲染性能content-visibility 与资源提示规则 6.2content-visibility给出针对长列表如 1000 条消息的 CSS 方案——浏览器可跳过约 990 个屏外条目的布局与绘制初始渲染最多可提速一个数量级.message-item { content-visibility: auto; contain-intrinsic-size: 0 80px; }规则 6.10React DOM 资源提示汇总了react-dom提供的 6 个 API 及适用场景prefetchDNS稍后连接的第三方域名、preconnect立即要 fetch 的 API/CDN、preload当前页关键资源、preloadModule很可能下一次导航用到的 JS 模块、preinit/preinitModule必须尽早执行的样式表/脚本/ES 模块。在 Server Component 中调用这些 API 可以让浏览器在收到 HTML 之前就开始加载资源。JavaScript 微优化Map 索引与不可变排序规则 7.2索引 Map把 1000 订单 × 1000 用户的users.find()内层查找从 100 万次操作降为约 2000 次const userById new Map(users.map(u [u.id, u])) return orders.map(order ({ ...order, user: userById.get(order.userId) }))规则 7.14toSorted强调 React 中.sort()会原地修改 props/state 数组破坏不可变模型、诱发陈旧闭包应改用.toSorted()以及.toReversed()、.toSpliced()、.with()等不可变方法族老环境用[...items].sort(...)兜底。高级模式useEffectEvent 与一次性初始化规则 8.1 指出useEffectEvent返回的函数身份刻意每次渲染都变化绝不能放进 effect 依赖数组会导致 effect 每次渲染重跑并触发 lint 告警应只依赖真实响应式值、在 effect 体内调用。规则 8.2init once建议用模块级 guard 标志避免应用级初始化在开发环境StrictMode 双调用与组件重挂载时重复执行let didInit false function Comp() { useEffect(() { if (didInit) return didInit true loadFromStorage() checkAuthToken() }, []) }如何新增一条规则贡献流程README 的 Creating a New Rule 与 Contributing 章节给出了完整的贡献流程这也是维护这套规则集的核心方法论复制rules/_template.md到rules/area-description.md根据目标 Section 选择正确的前缀async-第 1 节 消除瀑布、bundle-第 2 节 打包体积、server-第 3 节 服务端性能、client-第 4 节 客户端数据获取、rerender-第 5 节 重渲染优化、rendering-第 6 节 渲染性能、js-第 7 节 JS 性能、advanced-第 8 节 高级模式填写 frontmatter 与正文内容确保包含清晰的正反例与解释bad/good examples with explanations添加合适的 tags运行pnpm build重新生成AGENTS.md与test-cases.json。无需手工管理编号规则在各自 Section 内按标题自动排序ID 在构建时自动生成。所有规则文件集中存放于 .agents/skills/vercel-react-best-practices/rules/读者可按前缀浏览任意 Section 的完整规则正文例如async-parallel.md、bundle-barrel-imports.md、server-cache-lru.md、rerender-functional-setstate.md、js-tosorted-immutable.md、advanced-init-once.md。与 Comp AI CRM 工程实践的呼应本规则集并非孤立文档Comp AI CRM 的 Next.js 前端正在践行其中的多项规则可作为规则 → 源码的对照样本深路径导入规则 2.1如 sales-dashboard.tsx/[slug]/sales-dashboard.tsx) 从crm/ui/components/card、crm/ui/components/dashboard、crm/ui/components/stat-card、crm/ui/lib/format等子路径导入避免一次性加载整个crm/uibarrel重型组件动态导入规则 2.3/2.5dashboard-charts.tsx 使用next/dynamicssr: false loading 占位延迟加载图表并把模块路径固定为字面量Next.js 配置规则 2.x 相关apps/app/next.config.ts 中启用了cacheComponents: true与partialPrefetching: true以利用框架级缓存/预取能力通过transpilePackages显式声明需要转译的 workspace 包crm/auth、crm/db、crm/telemetry、crm/ui并用serverExternalPackages把prisma/client等留在服务端——这些配置都属于让打包器与运行时行为可预期的服务端性能范畴。结语把性能规范变成 Agent 可执行的资产Vercel React Best Practices 技能包的精髓在于它把性能最佳实践从一段人类阅读的长文拆解为带元数据、可编译、可校验、可评测的结构化规则集每条规则 一个文件名前缀 YAML frontmatter Incorrect/Correct 代码对照70 条规则按 8 个优先级分类通过pnpm build编译成统一的AGENTS.md供 Agent 消费通过pnpm extract-tests生成test-cases.json供 LLM 评测。对于 Comp AI CRM 这类以 AI Agent 为第一使用者的 CRM 产品这套机制保证了 AI 生成的 React/Next.js 代码能够稳定遵循从瀑布消除到微优化的一致范式。开发者既可以直接复用这 70 条规则作为审查清单也可以依照 README 的贡献流程把团队自身的性能经验沉淀为新的规则文件。【免费下载链接】crmComp AI CRM is an open source, CRM designed for AI agents. Agentic-first CRM.项目地址: https://gitcode.com/gh_mirrors/crm48/crm创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考