AgentSkillsCN

frontend-audit

当您需要对前端代码进行审计——包括组件架构、状态管理、无障碍性、设计系统的一致性、Bundle 大小,以及渲染性能——此技能同样不可或缺。它不拘泥于特定框架,但针对 React、Vue、Svelte 以及原生 JavaScript 提供了针对性的指导建议。

SKILL.md
--- frontmatter
name: frontend-audit
description: "Use when auditing frontend code — component architecture, state management, accessibility, design system consistency, bundle size, and rendering performance. Framework-agnostic with specific guidance for React, Vue, Svelte, and vanilla JS."

Frontend Audit

Overview

Frontend code is the user's direct experience. Architecture problems here manifest as bugs users can see and feel. A broken backend returns an error; a broken frontend returns confusion, frustration, and churn.

Core principle: The UI is the product. If the frontend is broken, nothing else matters to users.

The Iron Law

code
NO COMPONENT WITHOUT CLEAR RESPONSIBILITY. NO USER INPUT WITHOUT VALIDATION. NO ASYNC OPERATION WITHOUT ALL THREE STATES (LOADING, ERROR, EMPTY).

When to Use

  • Auditing frontend architecture
  • Reviewing component design
  • Investigating UI bugs or inconsistencies
  • Before major frontend refactoring
  • Performance-related UI complaints
  • During any codebase audit
  • After onboarding a new frontend framework

When NOT to Use

  • Pure backend API projects with no frontend
  • CLI tools (use architecture-audit instead)
  • Static marketing sites with no interactivity (a quick review of HTML semantics suffices)
  • If only a single isolated component needs review (use code-review instead)

Anti-Shortcut Rules

code
YOU CANNOT:
- Say "components look fine" — open each component file and check its line count, prop count, and responsibilities
- Say "state management is handled" — trace where each piece of state lives and why
- Say "design system is consistent" — grep for hardcoded values, check token adoption
- Judge accessibility by looking at code alone — test keyboard navigation manually
- Skip the bundle analysis — measure actual sizes, not guesses
- Trust component names — read the render method to understand true responsibility
- Say "similar to above" — each component gets its own row in the audit table

Common Rationalizations (Don't Accept These)

RationalizationReality
"It works, so it's fine"Working ≠ maintainable. 600-line components work but are unmaintainable.
"We'll refactor later"Later never comes. Component debt compounds faster than financial debt.
"Only one person works on the frontend"That person will leave. Or get sick. Or forget how it works in 6 months.
"It's just a simple form"Forms are the most complex UI pattern — validation, error states, accessibility, submission states.
"We don't need loading states yet"Users experience blank screens as crashes. Loading states are not optional.
"Design tokens are overkill for this project"Hardcoded values diverge within weeks. Tokens prevent visual entropy.
"Screen readers aren't our target audience"15% of users have disabilities. It's also a legal requirement in many jurisdictions.

Iron Questions (Ask Before Every Component Review)

code
1. If I gave this component to a new developer, could they understand its purpose in 30 seconds?
2. Can I describe what this component does in ONE sentence without using "and"?
3. If I delete this component, what exactly breaks and nothing else?
4. Does every prop this component receives actually change what it renders?
5. Could a user complete the primary action using ONLY a keyboard?
6. What does the user see during the 0-3 seconds between clicking and data loading?
7. What does the user see when there is NO data?
8. What does the user see when the API returns an error?
9. Is every pixel value traceable to a design token?
10. If the API is 10x slower than expected, does this component still behave reasonably?

The Audit Process

Phase 1: Component Architecture

code
1. MAP the component tree — what renders what (use the framework's devtools or trace imports)
2. IDENTIFY reusable vs one-off components — reusable should be in a shared directory
3. CHECK component responsibility — one component, one job (SRP)
4. FIND components > 200 lines — candidates for splitting
5. LOOK for prop drilling — data passing through 3+ layers without being used
6. CHECK for business logic in render — calculations, filtering, and formatting should be hooks/utils
7. VERIFY component naming — names should describe WHAT, not HOW

Component quality checklist:

CheckHealthyWarningUnhealthy
Lines of code< 150150-300> 300
Props count< 55-8> 10
Responsibilities1 clear purpose1 primary + 1 minor"It handles display, validation, and API calls"
State variables0-23-5> 5 (split component)
useEffect/watchers0-12-3> 3 (data fetching layer needed)
ChildrenComposition-basedSome inline rendersGiant render method with 10+ conditionals
Re-render triggersOnly when props changeSome unnecessary re-rendersRe-renders on every keystroke

Detection patterns:

bash
# Find oversized components (> 300 lines)
find . -name "*.tsx" -o -name "*.vue" -o -name "*.svelte" | xargs wc -l | sort -rn | head -20

# Find high prop count components
grep -c "interface.*Props" --include="*.tsx" -r . | grep -v node_modules | sort -t: -k2 -rn | head -20

# Find prop drilling (components passing through props they don't use)
grep -rn "\.\.\.props" --include="*.tsx" . | grep -v node_modules | head -20

# Find business logic in components (API calls in render files)
grep -rn "fetch\|axios\|\.get(\|\.post(" --include="*.tsx" --include="*.vue" . | grep -v node_modules | grep -v "hook\|service\|api\|util" | head -20

Phase 2: State Management

code
1. WHERE does state live? (local, global store, URL, server state)
2. IS the right kind of state in the right place?
3. ARE there state synchronization issues? (same data in two places getting out of sync)
4. IS derived state being stored instead of computed?
5. ARE effects (useEffect / watchers) cleaning up properly?
6. IS server state managed with a dedicated tool? (React Query, SWR, TanStack Query)
7. ARE there unnecessary re-renders caused by state updates?

State placement guide:

State TypeCorrect LocationWrong LocationWhy
Form input valuesLocal component stateGlobal storeForms are ephemeral; global state persists unnecessarily
Current user sessionGlobal store / contextLocal stateSession survives navigation
URL-derived stateURL params / searchParamsComponent stateMust survive refresh and be shareable
Server dataServer state (React Query, SWR)Local useStateServer data needs caching, refetching, invalidation
UI toggles (modals, dropdowns)Local stateGlobal storeUI state is component-scoped
Theme / preferencesContext / global storeProp drillingCross-cutting concern needs global access
Derived/computed valuesuseMemo / computedSeparate useStateStored derived state gets out of sync

Framework-specific state smells:

FrameworkSmellFix
ReactuseState + useEffect to sync server dataUse React Query / SWR
ReactMultiple useState that change togetheruseReducer or single state object
VueDeeply nested reactive objectsFlatten state or use computed
SvelteStore for component-local stateUse local reactive declarations
AllProp drilling through 4+ componentsContext / provide-inject / store

Phase 3: Design System Consistency

code
1. IS there a design system? (tokens, variables, shared components)
2. ARE components using shared tokens or ad-hoc values?
3. IS spacing consistent? (one spacing scale or random pixel values)
4. IS typography consistent? (defined font sizes or ad-hoc rem/px)
5. ARE colors from a palette or hardcoded hex values?
6. ARE breakpoints defined and consistent?
7. IS the component library documented?

Common violations:

ViolationDetectionFix
Hardcoded colorsgrep -rn "#[0-9a-f]\{3,6\}" --include="*.css" --include="*.tsx"Use var(--color-primary) or theme tokens
Hardcoded spacinggrep -rn "margin.*[0-9]px|padding.*[0-9]px" --include="*.css"Use spacing scale tokens (4, 8, 12, 16, 24, 32, 48)
Inline styles for layoutgrep -rn "style={{" --include="*.tsx"Use CSS classes or styled-components
Inconsistent breakpointsgrep -rn "max-width.*px|min-width.*px" --include="*.css"Define breakpoint tokens
Magic z-index valuesgrep -rn "z-index.*[0-9]" --include="*.css" --include="*.tsx"Define z-index scale (1, 10, 100, 1000)
Unsystematic font sizesgrep -rn "font-size" --include="*.css"Define type scale (xs, sm, md, lg, xl)
Mixed unit systemsBoth px and rem throughoutStandardize on rem with px fallbacks

Phase 4: Error, Loading, and Empty States

code
1. DOES every async operation have a loading state?
2. DOES every async operation have an error state with retry?
3. ARE empty states handled? (no data, no results, first use)
4. DO forms show validation errors clearly and next to the input?
5. DO failed submissions preserve user input?
6. IS there a global error boundary?
7. DO timeout/offline states have dedicated UI?

State coverage matrix (complete for EVERY component with async operations):

ComponentLoadingErrorEmptySuccessPartialTimeoutOffline
UserList✅ Skeleton✅ Retry❌ MissingN/A
Dashboard⚠️ Spinner❌ Generic

Quality standards per state:

StateMinimum AcceptableGold Standard
LoadingSpinner or skeletonContent-shaped skeleton with shimmer animation
ErrorError messageError message + retry button + help link
Empty"No items" textIllustration + explanation + call-to-action
SuccessData displayedSmooth transition with optional celebration
TimeoutGeneric error"Taking longer than expected" with retry
OfflineNothingOffline indicator with cached data if available

Phase 5: Accessibility (Quick Check)

code
1. DO images have descriptive alt text (not "image" or "photo")?
2. ARE interactive elements focusable and keyboard-accessible?
3. IS there visible focus style (not just browser default outline: none)?
4. DO form inputs have associated <label> elements?
5. ARE color contrast ratios sufficient (4.5:1 text, 3:1 components)?
6. DO modals trap focus correctly?
7. CAN the entire primary flow be completed with keyboard only?
8. IS there a skip navigation link?

(For deep accessibility audit, use accessibility-audit skill)

Phase 6: Bundle and Performance

code
1. WHAT is the total bundle size? (target: < 200KB initial, < 500KB total)
2. ARE there unnecessary dependencies? (moment.js, lodash full import, full icon packs)
3. IS code splitting used for routes?
4. ARE images optimized (WebP, responsive sizes, lazy loading)?
5. ARE heavy components lazily loaded?
6. IS tree shaking working? (no importing entire libraries for one function)
7. ARE fonts optimized (subset, preload, font-display: swap)?
8. ARE third-party scripts deferred?

Common bundle bloat sources:

DependencyTypical SizeLighter AlternativeSavings
moment.js284KBdayjs (2KB) or date-fns (tree-shakeable)~280KB
lodash (full)72KBlodash-es (tree-shakeable) or native~60KB
Material UI (full)400KB+Import individual components~300KB
Font Awesome (all)1.5MBOnly import used icons~1.4MB
Axios13KBNative fetch13KB

Detection:

bash
# Check bundle size (if available)
npx bundle-phobia [package-name]

# Find full library imports
grep -rn "import .* from 'lodash'" --include="*.ts" --include="*.tsx" . | grep -v node_modules
grep -rn "import .* from '@mui/material'" --include="*.ts" --include="*.tsx" . | grep -v node_modules

# Find unoptimized images
find . -name "*.png" -o -name "*.jpg" -o -name "*.jpeg" | xargs ls -la | sort -k5 -rn | head -10

Phase 7: Rendering Performance

code
1. ARE lists virtualized for > 100 items? (react-window, vue-virtual-scroller)
2. ARE expensive computations memoized? (useMemo, computed)
3. ARE component re-renders minimized? (React.memo, shouldComponentUpdate)
4. ARE event handlers debounced for high-frequency inputs? (search, resize, scroll)
5. IS there unnecessary DOM manipulation?
6. ARE animations using GPU-accelerated properties? (transform, opacity — not top, left, width)

Output Format

markdown
# Frontend Audit: [Project Name]

## Overview
- **Framework:** [React/Vue/Svelte/Vanilla]
- **Components:** N total, N reusable, N one-off, N oversized (>300 LOC)
- **Bundle Size:** XKB initial / XKB total
- **Design System:** Comprehensive / Partial / Missing
- **State Management:** [Library/approach]
- **Accessibility:** WCAG AA Compliant / Partial / Non-compliant

## Component Health
| Component | Lines | Props | State Vars | Responsibilities | States Covered | Assessment |
|-----------|-------|-------|------------|------------------|----------------|------------|
| UserDashboard | 450 | 12 | 8 | Display, fetch, filter | Loading only | 🔴 Split needed |
| LoginForm | 85 | 3 | 2 | Auth form | All 4 | 🟢 Healthy |

## State Management Assessment
| State Type | Location | Assessment |
|-----------|----------|------------|
| Server data | React Query | 🟢 Correct |
| Form state | Local useState | 🟢 Correct |
| User session | Redux store | 🟢 Correct |
| Derived values | Separate useState | 🔴 Should be useMemo |

## Design System Compliance
| Check | Violations | Assessment |
|-------|-----------|------------|
| Hardcoded colors | 23 instances | 🟠 High |
| Hardcoded spacing | 45 instances | 🔴 Critical |
| Inline styles | 12 instances | 🟡 Medium |

## Bundle Analysis
| Chunk | Size | Assessment |
|-------|------|------------|
| Main | 180KB | 🟢 Under 200KB |
| Vendor | 350KB | 🟡 Could tree-shake |

## Findings
[Standard severity format — sorted by severity]

## Summary
| Severity | Count |
|----------|-------|
| 🔴 Critical | N |
| 🟠 High | N |
| 🟡 Medium | N |
| 🟢 Low | N |

## Verdict: [PASS / CONDITIONAL PASS / FAIL]

Red Flags — STOP and Investigate

  • Components > 500 lines (god components)
  • Prop drilling through 4+ levels
  • Business logic in UI components (API calls, calculations in render)
  • No loading/error/empty states on async components
  • Hardcoded strings (no i18n preparation)
  • No design tokens (all ad-hoc values)
  • Direct DOM manipulation in framework components
  • any types in TypeScript component props
  • Console.log statements in production code
  • Inline styles for layout that should be CSS
  • No error boundary at the application root
  • Z-index values > 9999 (z-index wars)

Integration

  • Part of: Full audit with architecture-audit
  • Deep dive: accessibility-audit for WCAG compliance
  • Performance: performance-audit for rendering metrics
  • Design verification: product-completeness-audit for visual completeness
  • API connection: full-stack-api-integration for data flow verification