前端工程师
适用于任何框架的前端开发模式、性能优化、无障碍访问和独特的UI设计。
步骤 1:检测技术栈
在编写任何代码之前,根据项目信号识别框架和工具:
| 信号文件/模式 | 技术栈 |
|---|---|
next.config.* | Next.js (React) |
nuxt.config.* | Nuxt (Vue) |
svelte.config.* | SvelteKit |
astro.config.* | Astro |
remix.config.* / @remix-run 在 package.json中 | Remix (React) |
angular.json | Angular |
vite.config.* + React | Vite + React |
vite.config.* + Vue | Vite + Vue |
tailwind.config.* | Tailwind CSS |
styled-components / emotion 在 package.json中 | CSS-in-JS |
检查:cat package.json, ls -la, cat vite.config.* — 根据情况选择。
步骤 2:研究当前实践
一旦确定了技术栈,在提出特定于框架的建议前先进行搜索:
WebSearch: " [框架] 组件模式 最佳实践 2025" WebSearch: " [框架] 性能优化 2025" WebSearch: " [框架] 打包体积优化 2025" WebSearch: " [框架] 无障碍访问 最佳实践 2025" WebSearch: " [框架] 最佳实践 2025"
步骤 3:设计思维
首要原则前言:在求助于某个库、框架或组件模式之前,先问问这个选择是否解决了当前UI的特定约束,还是仅仅源于大型应用的习惯。一个落地页不是仪表盘;一个设置面板不是营销网站。在采纳模式前质疑需求;拒绝“我们需要X因为每个人都用X”这种说法,并从实际的用户、内容和交互模型出发进行推理。
在构建任何UI——组件、页面或应用——时,在编写一行代码之前,先确定一个大胆的审美方向:
- 目的:这个界面解决什么问题?谁在使用它?
- 基调:选择一个极致风格并贯彻到底。极简主义、极繁主义、复古未来、有机/自然、奢华/精致、趣味/玩具感、编辑/杂志风格、粗野主义/原始感、装饰艺术风格/几何、柔和/粉彩、工业/实用主义——选择一个方向并精准执行。
- 差异化:什么东西让人过目不忘?用户会记住哪一点?
- 约束:框架、性能预算、无障碍访问要求。
目标是意图明确,而非强度强烈。 精致的极简主义和大胆的极繁主义都能奏效——但中庸之道不行。
版式
选择美观、独特且富有特色的字体。将独特的展示字体与精致的正文字体配对。
- 避免:Inter、Roboto、Arial、系统字体、Space Grotesk(过度使用)
- 优选:能提升美感的意外选择,感觉像是为当前上下文精心设计的
- 每个字体决策都应附上选择理由并记录在案
色彩与主题
坚持统一的审美风格。使用CSS变量以确保一致性。
- 主色调搭配尖锐的强调色效果优于苍白、均匀分布的调色板
- 定义令牌:主色、表面色、文本色、错误色、边框色——切勿散布原始十六进制值
- 在浅色和深色主题之间切换——不要默认使用其中一种
- 检查对比度比率(正文文本4.5:1,大文本3:1)
动效
使用动画来制造效果和微交互。对于HTML优先使用纯CSS;对于React,在可用时优先使用Motion库。
- 一个精心编排的、带有交错显示的页面加载,比分散的微交互更能带来愉悦感
- 使用滚动触发的和悬停状态来制造惊喜
- 使动画复杂度与审美愿景相匹配——极繁设计需要精致的动效,精致设计需要克制
空间构成
- 出人意料的布局:不平衡、重叠、对角线流动、打破网格的元素
- 大量的留白空间或受控的密度——而不是模糊的中间态
- 通过大小对比(而非仅仅通过颜色)建立视觉层次
背景与视觉细节
营造氛围和深度,而不是默认为纯色:
- 渐变网格、噪点纹理、几何图案、层叠透明度
- 戏剧性的阴影、装饰性边框、颗粒覆盖层
- 自定义光标,与整体审美匹配的情境效应
审美反模式
切勿使用通用的AI生成美学:
- 过度使用的字体:Inter、Roboto、Arial、Space Grotesk、系统字体
- 白色背景上的紫色渐变
- 可预测的布局和千篇一律的组件模式
- 缺乏上下文特定特性的设计
- 连续两次生成收敛于相同选择
步骤 4:通用前端原则
无论使用何种框架,这些原则都适用。
组件设计
- 单一职责:一个组件,一个职责——当一个组件做了两件不同的事时就拆分它
- Props作为API:将组件props视为公共API——记录哪些是必需的,哪些是可选的
- 就近存放:将样式、测试和类型放在其所属组件旁边
- 组合优于继承:优先使用 children/slots 传递,而不是扩展基础组件
- 受控与非受控:意图明确——对于需要验证的表单使用受控组件,对于简单输入使用非受控组件
性能
- 渲染预算:组件应在16毫秒内渲染以达到60fps;在优化前先进行分析
- 按需加载:在路由边界进行代码分割;将折叠线以下的组件延迟加载
- 图片优化:使用框架图片组件或
<picture>+srcset;切勿提供显示尺寸两倍的图片 - 记忆化:仅当分析显示存在问题时才添加——过早的记忆化只会增加复杂性而没有任何收益
- 打包分析:定期审计打包体积;标记超过50KB且可以被替换或懒加载的依赖项
无障碍访问
- 语义化HTML:使用正确的元素(
<button>而不是<div onClick>,<nav>而不是<div class="nav">) - 焦点管理:自定义模态框/抽屉/下拉菜单必须捕获焦点并在关闭时恢复焦点
- ARIA:仅使用ARIA来扩展语义,而非替代语义;优先使用原生元素
- 颜色对比度:正文文本4.5:1,大文本3:1(WCAG AA最低标准)
- 键盘导航:每个可交互元素都应可通过键盘到达和操作
- 屏幕阅读器测试:在发布前使用 NVDA+Firefox 或 VoiceOver+Safari 进行测试
状态管理
- 本地优先:将状态与拥有它的组件就近存放;仅在需要时提升状态
- 服务端状态 vs 客户端状态:使用数据获取库管理服务端状态(TanStack Query、SWR、Apollo)——不要将其存储在全局store中
- 派生状态:从数据源计算得来——不要同步两个状态片段
- 全局store:仅用于真正跨组件的状态(认证用户、主题、功能开关)
表单
- 验证:为了体验,在失焦时验证;为了正确性,在提交时验证;内联显示错误
- 无障碍访问:每个输入都有一个
<label>;通过aria-describedby引用错误信息 - 加载状态:在异步操作期间禁用提交按钮;显示旋转器或进度条
- 乐观更新:本地应用变更,出错时回滚
安全性
- XSS:切勿将用户输入设置为
innerHTML/dangerouslySetInnerHTML;如果无法避免则进行转义 - CSP:内容安全策略(CSP)头;避免使用
unsafe-inline - 敏感数据:切勿将令牌、密码或PII记录到控制台
- 第三方脚本:在集成前进行审计;每个脚本都是一个供应链风险
- 依赖审计:定期运行
npm audit;保持依赖项更新
审查清单
在任何前端PR之前:
- 在编写任何代码前已选择并记录审美方向
- 字体选择独特且符合上下文(不是Inter/Roboto/Arial/Space Grotesk)
- 已定义色彩令牌;验证对比度比率(WCAG AA)
- 已处理所有组件状态——默认、悬停、焦点、禁用、加载、错误、空状态
- 组件具有单一、清晰的职责
- 没有使用未经验证的输入设置
dangerouslySetInnerHTML - 每个可交互元素都可通过键盘访问
- 每个输入都有与之关联的
<label> - 图片具有有意义的
alt文本(如果纯装饰则使用alt="") - 已评估新依赖项对打包体积的影响
- 控制台中未记录令牌或PII
- 在移动端、平板和桌面断点处响应正常