mcpField
E
engineering-frontend-developer

engineering-frontend-developer

github.com/peterhdd开发11242 次安装33 周前更新
代码仓库

关于 engineering-frontend-developer

面向前端开发者的指南,涵盖 React、Vue、Angular 和 Svelte 应用、组件库及性能优化。它通过具体决策规则指导布局、无障碍、测试、构建工具和渲染方案的选择。

主要功能

  1. 01React、Vue、Angular 和 Svelte 指南
  2. 02组件架构与 TypeScript 约定
  3. 03性能分析与优化决策
  4. 04无障碍实现和测试规则
  5. 05构建工具及 SSR、CSR、SSG 选择

适用场景

  1. 01规划新 Web 应用的框架与构建工具
  2. 02排查布局、性能或水合问题
  3. 03构建组件库并检查无障碍要求

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/peterhdd/agent-skills --skill engineering-frontend-developer

安装后在 Claude Code 中输入/engineering-frontend-developer确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
css-patterns.md
data-table.md
react-patterns.md
typescript-patterns.md
scripts/
check_bundle.sh

详细介绍

前端开发指南

概述

本指南涵盖使用 React、Vue、Angular 和 Svelte 进行现代前端开发,包括组件架构、性能优化、无障碍访问和测试。构建 Web 应用、组件库或优化前端性能时,请使用本指南。

框架和布局决策规则

  • 选择框架时,应结合团队的专业知识和项目限制;生态系统广泛时默认选择 React;需要渐进式增强现有页面时选择 Vue;对包体积要求严格的应用选择 Svelte;项目需要内置 DI 和路由且约定明确的全功能框架时选择 Angular。
  • 实现设计时,使用 CSS Grid 进行二维页面布局,使用 Flexbox 对齐一维组件;避免将绝对定位用于布局,因为这会破坏响应式重排。
  • 构建组件库时,每个组件都应作为具名导出提供,并包含 TypeScript props 接口、Storybook story 和单元测试;缺少其中任何一项的组件都不会被合并。
  • 与后端 API 集成时,应将 fetch 逻辑集中到有类型的 API 客户端层(例如,使用 fetch 或 axios 和拦截器的单个 api.ts 模块),以便在同一处处理身份验证标头、错误转换和重试。

性能决策规则

  • 如果页面在 Lighthouse CI 中的最大内容绘制耗时超过 2.5 秒,应将其视为阻塞性错误;使用 Chrome DevTools 的 Performance 标签页进行分析,并在合并前修复最大的瓶颈。
  • 添加动画时,使用 CSS 的 transform 和 opacity 属性(仅由合成器处理),而不要使用 width、height 或 top/left,以避免触发导致卡顿的布局重新计算。
  • 应用需要离线支持时,为静态资源注册采用缓存优先策略的 service worker,为 API 请求注册采用网络优先策略的 service worker,并在离线时回退到缓存响应。
  • 初始 JS 包超过预算(例如,压缩后为 200 KB)时,使用 React.lazy() 或动态 import() 添加基于路由的代码拆分,并延迟加载首屏以下的非关键脚本。
  • 支持旧版浏览器时,定义 browserslist 配置,并让构建工具(Vite、Webpack)自动添加 polyfill;除非 browserslist 覆盖不足,否则不要手动添加 polyfill 或功能检测。
  • 添加图片时,使用 <picture> 和 WebP/AVIF 源,并显式设置 width/height 属性以防止布局偏移;对于首屏以下的图片,添加 loading="lazy"。
  • 如果某个路由在初始页面加载时不需要,应使用 React.lazy()(或框架的等效功能)和 <Suspense> 回退将其封装起来,使主包不包含该路由的代码。
  • 提供静态资源时,应配置 CDN 或服务,在带内容哈希的文件名上设置 Cache-Control: public, max-age=31536000, immutable,并在 index.html 上设置 no-cache。

无障碍访问决策规则

  • 构建任何交互组件时,都应添加 ARIA 属性、键盘处理程序(按需支持 Enter、Space、Escape),并在标记任务完成前使用 axe-core 测试。
  • 构建表单时,使用 htmlFor/id 将每个 <input> 与 <label> 关联,提供通过 aria-describedby 关联的可见错误消息,并确保仅使用键盘导航也能完整操作表单。
  • 使用颜色传达含义(例如,错误状态、状态徽章)时,务必添加辅助指示(图标、文本、图案),以便色盲用户区分状态。
  • 添加模态框或下拉菜单时,在其打开期间将焦点限制在元素内,并在关闭时将焦点返回触发元素;通过不使用鼠标而用 Tab 键完成整个流程进行测试。
  • 拉取请求新增交互组件时,必须包含 axe-core 集成测试,断言不存在 WCAG 2.1 AA 违规,才能合并。

CSS 调试决策规则

布局出问题时,请根据症状进行诊断:

  • Flex 子项溢出其容器:为 Flex 子项添加 min-width: 0(行布局)或 min-height: 0(列布局)。Flex 项的默认值为 min-width: auto,这会阻止其缩小到内容尺寸以下。
  • Grid 项忽略列宽:使用 minmax(0, 1fr),而不是 1fr。单独使用 1fr 意味着 minmax(auto, 1fr),会让内容撑大列宽,超出预期。
  • position: sticky 不生效:检查所有祖先元素是否设置了 overflow: hidden、overflow: auto 或 overflow: scroll。这些属性都会创建新的滚动上下文,并将 sticky 元素限制在其中。同时确认元素已设置 top/bottom 值。
  • 使用 margin: auto 居中的元素没有居中:确认元素设置了明确的 width(块级元素),或父元素设置了 display: flex(Flex 子项)。对全宽块级元素使用 margin: auto 不会生效。
  • z-index 不生效:元素需要设置 position: relative/absolute/fixed/sticky 才能创建堆叠上下文。同时检查祖先元素是否通过 transform、opacity < 1、filter 或 will-change 创建了堆叠上下文,从而限制 z-index 的作用范围。
  • inline-block/inline 元素之间有间隙:HTML 中的空白字符会产生间隙。修复方法:在父元素上使用 display: flex(首选),或将父元素的 font-size 设为 0,并在子元素上重置。
  • 相邻元素之间有 1px 间隙:这是亚像素渲染导致的。修复方法:调试时使用 outline 代替 border,或为父元素设置 background 以遮盖间隙。
  • 文本省略截断不生效:必须同时设置 overflow: hidden、white-space: nowrap 和 text-overflow: ellipsis。多行截断时,使用 -webkit-line-clamp,并设置 display: -webkit-box 和 -webkit-box-orient: vertical。
  • 容器查询未生效:确认祖先元素设置了 container-type: inline-size(或 size)。元素自身不能作为自己的容器,查询必须引用父元素。

构建工具决策规则

  • Vite(默认):所有新项目都使用 Vite。通过原生 ESM 提供即时开发服务器、快速 HMR 和基于 Rollup 的生产构建。如果项目使用了与 Vite 不兼容的 CommonJS 专用依赖,为这些包添加 optimizeDeps.include,不要切换到 Webpack。
  • Webpack:仅用于已经使用 Webpack 的现有项目,或特定的 Webpack 专用插件没有 Vite 等效方案的情况(很少见)。有机会时迁移到 Vite(参见迁移决策规则)。
  • Turbopack:仅在 Next.js 14+ 中使用(next dev --turbo)。目前还不能独立使用。对于 Next.js 项目,其开发构建速度比 Webpack 更快。如果构建已经很快(<5s),就不必切换。
  • esbuild:用于库打包、脚本或 CLI 工具,不用于完整应用。不支持 HTML 入口点处理,也不支持按路由拆分代码。发布 npm 包时使用 tsup(esbuild 封装器)。
  • SWC 与 Babel:使用 SWC(通过 Vite 插件或 Next.js 默认配置)。SWC 的转换速度快 20-70 倍。仅当项目依赖没有 SWC 等效方案的 Babel 专用插件时才使用 Babel(这种情况越来越少)。
  • Monorepo 工具:少于 5 个包时使用 npm/pnpm workspaces,不需要额外工具。5-20 个包时使用 Turborepo 缓存任务。超过 20 个包或涉及多种语言时使用 Nx。单包项目绝不要添加 Monorepo 工具。

SSR 和服务器组件决策规则

何时使用 SSR、CSR 或 SSG
  • SSG(静态站点生成):适用于每小时更新不到一次的内容(营销页面、文档、博客文章)。在部署时构建。TTFB 尽可能快。
  • SSR(服务器端渲染):适用于个性化内容(仪表板、用户个人资料)、SEO 至关重要且包含动态数据的页面,或不能接受数据过时的页面。每次请求都会增加服务器延迟——使用 Cache-Control 或 CDN 积极缓存。
  • CSR(客户端渲染):适用于仅限已认证用户访问的页面(管理面板、内部工具),这类页面不需要考虑 SEO,交互性是首要目标。构建和部署最简单(静态托管)。
  • ISR(增量静态再生成):适用于大多为静态内容、但需要定期更新的页面(商品列表、价格页面)。根据数据可过时的时长设置 revalidate 间隔:价格设为 60s,博客文章设为 3600s。
React Server Components(RSC)决策规则
  • 默认使用 Server Components:除非组件需要交互功能,否则都使用 Server Component。如果组件包含 onClick、useState、useEffect 或浏览器 API,就必须是 Client Component('use client')。
  • 数据获取:直接在 Server Components 中使用 async/await 获取数据——不需要 useEffect、TanStack Query 或加载状态。HTML 发送之前,数据就已解析完成。
  • 在 Server Components 中进行身份验证:在 Server Component 中读取会话/ Cookie,并将用户对象作为 prop 传递给 Client Components。不要在 Client Components 中读取 Cookie 或会话——它们在客户端执行。
  • 何时使用 Server Actions,何时使用 API 路由:对于从 UI 调用的表单提交和数据变更,使用 Server Actions('use server')。对于 Webhook、第三方集成或由外部服务调用的端点,使用 API 路由(/api/*)。
  • 在 Server Components 和 Client Components 之间共享状态:将可序列化数据作为 prop 从 Server 传递给 Client。如果需要基于服务器数据派生客户端状态,请使用服务器 prop 初始化 useState,并在客户端管理更新。
  • 大型数据集:使用 <Suspense> 边界进行流式传输。将较慢的 Server Component 放在 <Suspense fallback={<Skeleton />}> 中。页面外壳会立即渲染;较慢的组件准备就绪后再流式传输。将 Suspense 边界放在有意义的 UI 区块(侧边栏、主要内容、评论)上,而不是包裹每个组件。
水合错误决策树
  • 错误:“Text content does not match”:服务器渲染和客户端渲染的值不同。常见原因:
    1. 在渲染时使用 Date.now()、Math.random() 或 new Date().toLocaleString() → 移至 useEffect + useState。
    2. 使用 typeof window !== 'undefined' 条件渲染 → 使用 useEffect 设置 hasMounted 标志。
    3. 浏览器扩展注入 DOM 节点 → 这不是你的问题,但可以在无痕模式下测试确认。
  • 错误:“Hydration failed because the server rendered HTML didn't match”:结构不同(元素不同)。常见原因:
    1. 在 <p> 中嵌套 <p>,或在 <p> 中嵌套 <div> → 修正嵌套方式;HTML 规范不允许这样做。
    2. 第三方组件在服务器和客户端的渲染结果不同 → 使用 dynamic(() => import(...), { ssr: false }) 包裹。
    3. 缺少结束标签,或 HTML 要求显式闭合的标签使用了自闭合写法。

性能调试工作流

页面变慢时,请按以下顺序操作——不要跳过步骤:

步骤 1:确定瓶颈类型
  • 运行 Lighthouse。检查哪个指标未达标:
    • LCP >2.5s:最大的可见元素加载过慢。转到步骤 2。
    • FID/INP >200ms:JavaScript 阻塞了用户交互。转到步骤 3。
    • CLS >0.1:首次绘制后布局发生偏移。转到步骤 4。
步骤 2:修复 LCP
  1. 检查 LCP 元素是什么(Lighthouse 会显示)。通常是:首屏主图、标题文本或视频。
  2. 如果是图片:添加 priority(Next.js)或 fetchpriority="high"。明确设置 width/height。使用 WebP/AVIF 格式提供图片。如果图片由 CDN 提供,请检查缓存标头。
  3. 如果是文本:检查是否有阻塞渲染的字体。使用 font-display: swap 或 font-display: optional。使用 <link rel="preload" as="font" crossorigin> 预加载关键字体文件。
  4. 如果被 JS 阻塞:说明代码包太大。请查看步骤 3。创建 LCP 元素的 JS 加载并执行之前,该元素无法渲染。
  5. 检查服务器响应时间(TTFB)。如果 TTFB >600ms,瓶颈在后端或 CDN,而非前端。
步骤 3:修复 INP(交互到下一次绘制)
  1. 打开 Chrome DevTools → Performance → 记录一次点击/输入交互。
  2. 找到长任务(>50ms 的黄色条)。点击它以查看调用堆栈。
  3. 如果长任务来自你的代码:使用 requestIdleCallback、scheduler.yield()(Chrome 115+)或 setTimeout(fn, 0) 将工作拆分成更小的块,让出执行权,使浏览器能够在帧之间处理其他任务。
  4. 如果长任务来自 React 重渲染:打开 React DevTools Profiler。找到触发重渲染的组件。常见修复方法:使用 React.memo(开销较大的子组件)、useMemo(派生值),或将状态移至更靠近其使用位置的地方。如果单次状态更改导致 >500 个组件重渲染,说明状态放得太靠上了。
  5. 如果长任务来自第三方脚本(分析、广告):使用 async 或 defer 属性延迟加载,或者在 requestIdleCallback 后加载。
步骤 4:修复 CLS
  1. 检查哪个元素发生了位移(Lighthouse 会显示,或者使用 DevTools → “Layout Shift Regions”)。
  2. 没有尺寸的图片/视频:添加 width 和 height 属性(或使用 aspect-ratio CSS)。浏览器会在资源加载前预留空间。
  3. 字体切换:回退字体与 Web 字体的度量指标不同。使用 @font-face 中的 size-adjust 匹配度量指标,或者使用 font-display: optional 完全消除字体切换。
  4. 在首屏上方注入动态内容:广告、横幅、Cookie 提示。通过在容器上设置 min-height 来预留空间。如果内容高度不固定,请使用 contain: layout,避免位移向外传播。
  5. 延迟加载的 CSS:如果样式表在首次绘制后加载并更改可见布局,请内联关键 CSS,或预加载样式表。

代码质量决策规则

  • 编写测试时,要求每个组件至少有一个覆盖其主要渲染路径的单元测试,以及一个交互测试(点击、键盘)——通过 CI 覆盖率门槛强制要求行覆盖率至少达到 80%。
  • 启动项目时,第一天就在 tsconfig.json 中启用 strict: true;随着代码库增长,之后再补上严格模式会变得越来越困难。
  • API 调用或异步操作失败时,显示面向用户的错误消息并提供重试操作——绝不静默吞掉错误或显示原始异常文本。
  • 组件文件超过 300 行时,将其拆分为更小的子组件,并使用共享的 barrel export;大型文件通常意味着职责混杂。
  • 设置 CI 时,将 lint(ESLint)、类型检查(tsc --noEmit)、测试(Vitest/Jest)和代码包大小检查设为必需门槛——合并前这四项必须全部通过。

工作流

步骤 1:项目设置与架构
  • 使用合适的工具配置现代开发环境。
  • 配置构建优化和性能监控。
  • 建立测试框架并集成 CI/CD。
  • 创建组件架构和设计系统基础。
步骤 2:组件开发
  • 创建类型完善、可复用的组件库。
  • 采用移动优先的方法实现响应式设计。
  • 从一开始就在组件中融入无障碍功能。
  • 为所有组件编写全面的单元测试。
步骤 3:性能优化
  • 实施代码拆分和延迟加载策略。
  • 优化图片和资源,以便在 Web 上交付。
  • 监控 Core Web Vitals 并据此进行优化。
  • 设置性能预算和监控。
步骤 4:测试和质量保证
  • 编写全面的单元测试和集成测试。
  • 使用真实的辅助技术进行无障碍测试。
  • 测试跨浏览器兼容性和响应式行为。
  • 为关键用户流程实施端到端测试。

参考

Lighthouse CI 目标
  • 性能得分:90+
  • 所有交互元素均可通过键盘导航,并显示焦点指示器
  • axe-core:符合 WCAG 2.1 AA 级别,违规数为零
  • 包大小:初始 JS 经 gzip 压缩后 < 200 KB(使用 bundlesize 或同等工具强制执行)
  • 生产代码中不使用 TypeScript any 类型断言;在 tsconfig 中启用 strict: true

迁移决策规则

  • CRA 迁移到 Vite:当 CRA 的构建时间超过 30s 或弃用 CRA 的压力增大时进行迁移。步骤:将 react-scripts 替换为 vite + @vitejs/plugin-react,将 index.html 移至根目录,将 process.env 更新为 import.meta.env,修复所有 CommonJS 导入。预算:小型应用需 2-4 小时,大型应用(使用自定义 Webpack 配置)需 1-2 天。
  • Pages Router 迁移到 App Router(Next.js):增量迁移。每次将一个路由移至 app/ 目录。从静态/简单页面开始,将复杂页面(包含 getServerSideProps + 复杂状态)留到最后。不要一次性迁移整个应用。预算:复杂应用每天迁移 1 个路由。
  • JavaScript 迁移到 TypeScript:在 tsconfig 中启用 allowJs: true,然后逐个将文件从 .js 重命名为 .tsx。从叶子组件(无依赖项)开始,逐步向内推进。从第一天起就在新文件中强制启用 strict: true;如有需要,可创建一个扩展基础配置的 tsconfig.strict.json。预算:每天约 10 个文件。
  • CSS Modules 迁移到 Tailwind:不要一次性重写所有样式。在安装 Tailwind 的同时保留 CSS Modules。新组件使用 Tailwind;只有在因其他原因修改旧组件时,才迁移这些组件。预算:在日常开发中逐个组件迁移。
  • 类组件迁移到 hooks:仅在因功能变更需要修改组件时才迁移。不要迁移稳定且未修改的类组件——它们运行良好。迁移时:componentDidMount → useEffect(..., []),componentDidUpdate → 带依赖项的 useEffect,this.state → useState。

状态管理决策矩阵

  • 共享状态的组件少于 5 个:通过 props 向上提升状态。无需使用库。如果 props 逐层传递超过 3 层,则为该特定状态切片添加 React Context。
  • 共享状态的组件为 5-15 个:对于结构化状态,使用 React Context + useReducer;对于更简单的 API,使用 Zustand。如果状态是服务端数据,则使用 TanStack Query,而不是 Context。
  • 组件超过 15 个或派生状态复杂:使用 Zustand(简单、包体积小)或 Jotai(原子化、自底向上)。只有团队已熟悉 Redux 时才使用 Redux Toolkit。切勿在新项目中引入 Redux。
  • 服务端状态(API 数据、缓存、同步):使用 TanStack Query(React)、SWR(需求较简单)或 Apollo Client(GraphQL)。切勿将服务端数据存储在客户端状态管理器(Zustand、Redux)中——这会导致数据过期和重复的缓存管理。
  • 表单状态:复杂表单(字段超过 5 个、需要验证或包含动态字段)使用 react-hook-form。简单表单(字段少于 5 个、无复杂验证)使用原生 useState。切勿使用全局状态管理器管理表单状态。
  • URL 状态(筛选、分页、搜索):使用 URL 搜索参数(useSearchParams)作为唯一数据源。仅对派生值同步到组件状态。这样状态便于分享、添加书签,并支持浏览器返回按钮。

自我验证协议

完成前端实现后,请进行验证:

  • 运行 Lighthouse CI,并确认:Performance >=90、Accessibility >=90、Best Practices >=90。如果任何分数低于 90,请在合并前修复。
  • 对每个新增页面/组件运行 npx axe-core 或 axe-playwright。确保没有 WCAG 2.1 AA 违规。
  • 测试键盘导航:使用 Tab 键遍历整个页面。每个交互元素都必须可访问且可操作。焦点指示器必须清晰可见。
  • 打开浏览器 DevTools 的 Performance 面板,记录一次用户交互,并检查是否存在:布局抖动(强制重排)、超过 50ms 的长任务、过多的重新渲染。
  • 检查打包体积:运行 npx bundlesize 或查看构建输出。如果初始 JS 的 gzip 压缩后体积超过 200KB,请检查打包内容(使用 npx source-map-explorer)。
  • 在 320px、768px 和 1280px 的视口宽度下测试响应式布局。不得出现水平滚动、元素重叠或文本无法阅读的情况。
  • 将浏览器 DevTools 的网络限速设为 "Slow 3G" 并进行测试。如果页面无法正常使用,请添加加载状态并优化关键渲染路径。

故障恢复

  • 组件重新渲染过于频繁:使用 React DevTools Profiler 找出原因。常见修复方法:使用 React.memo 进行记忆化(适用于开销较大的子组件),使用 useMemo/useCallback 记忆化传递给 props 的派生值/回调,或将状态移至更接近其使用位置的地方。
  • 打包体积突然增大:运行 source-map-explorer 找出原因。常见原因:导入整个库(import _ from 'lodash' → import groupBy from 'lodash/groupBy')、意外打包了开发依赖,或引入了体积较大的 polyfill。
  • Hydration 不匹配(SSR/SSG):服务端渲染的 HTML 与客户端渲染结果不同。常见原因:在渲染过程中使用 Date.now() 或 Math.random()、在 SSR 期间访问 window/document,或根据仅客户端状态进行条件渲染。修复方法:使用 useEffect 处理仅客户端的值,或将 suppressHydrationWarning 作为最后手段。
  • CSS 布局在特定视口下错乱:检查是否存在:硬编码的像素宽度、Flex 子项缺少 min-width: 0、overflow: hidden 裁剪内容,或 position: absolute 元素脱离其容器。使用带 minmax() 的 CSS Grid 代替固定宽度。
  • API 调用过于频繁:检查 useEffect 依赖数组是否缺失或不正确。如果使用 TanStack Query,请设置 staleTime,避免每次挂载时都重新获取数据。如果使用 useEffect 获取数据,可考虑改用数据获取库。

熟悉现有代码库

加入现有前端项目时:

  1. 运行 npm start / npm run dev(5 分钟)——如果运行失败,请先修复开发环境。
  2. 检查技术栈(5 分钟)——框架(React/Vue/Angular/Svelte)、打包工具(Vite/Webpack/Turbopack)、CSS 方案(Tailwind/CSS Modules/styled-components)、状态管理和测试库。
  3. 运行测试套件(5 分钟)——运行 npm test。记录覆盖率、测试类型以及未覆盖的流程。
  4. 打开浏览器 DevTools(10 分钟)——检查打包体积(Network 面板)、控制台错误和 Lighthouse 分数。这些是基准数据。
  5. 阅读组件树(10 分钟)——从应用根节点开始。梳理顶层路由及其关键组件。找出共享组件(设计系统、布局)。
  6. 检查技术债迹象(5 分钟)——是否有 any 类型断言?eslint-disable 注释?超过 500 行的文件?内联样式?这些都表明相关区域较脆弱。
  7. 梳理数据流(10 分钟)——数据如何从 API 到达 UI?是否有集中式 API 客户端?是否有加载/错误状态?服务端状态是通过库还是手动管理的?

脚本

  • scripts/check_bundle.sh —— 分析构建输出目录中的 JS 和 CSS 包大小,并估算 gzip 压缩后的大小,支持配置警告和错误阈值。运行时使用 --help 查看选项。

请参阅DataTable 组件,了解使用 React + TypeScript 实现的完整虚拟化 DataTable。 请参阅React 组件模式,了解复合组件、自定义钩子、错误边界、乐观 UI 和表单验证模式。 请参阅TypeScript 模式,了解可辨识联合、多态组件、品牌类型和类型安全的 API 客户端。 请参阅CSS 模式,了解现代 CSS Grid 布局、容器查询、主题设置、视图过渡和 :has() 选择器。

评论

支持 Markdown