mcpField
S
senior-frontend

senior-frontend

github.com/alirezarezvani开发29.0k1.7k 次安装今天更新
代码仓库

关于 senior-frontend

senior-frontend 是面向 React 和 Next.js 项目的前端开发技能,涵盖项目搭建、组件生成、包体积分析和实现指导。其决策流程依据项目约束以及可衡量的性能和无障碍目标。

主要功能

  1. 01搭建 Next.js 和 React 项目
  2. 02生成组件、钩子、测试与 Storybook 文档
  3. 03分析包体积和依赖
  4. 04提供 React 与 Next.js 指导
  5. 05按项目约束匹配配置档

适用场景

  1. 01创建 TypeScript 前端项目
  2. 02生成带测试的可复用组件
  3. 03查找包中的大型依赖
  4. 04选择渲染方式和性能目标

安装

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

$npx skills add https://github.com/alirezarezvani/claude-skills --skill senior-frontend

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

包含的文件

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

profiles/
astro-or-static.json
next-app-router.json
remix-or-sveltekit.json
vite-spa.json
references/
composition_map.md
forcing_questions.md
frontend_best_practices.md
nextjs_optimization_guide.md
react_patterns.md
scripts/
bundle_analyzer.py
component_generator.py
frontend_decision_engine.py
frontend_scaffolder.py

详细介绍

Senior Frontend

面向 React/Next.js 应用的前端开发模式、性能优化与自动化工具。

目录


项目脚手架

生成一个使用 TypeScript、Tailwind CSS 以及最佳实践配置的新 Next.js 或 React 项目。

工作流:创建新的前端项目
  1. 使用项目名称和模板运行脚手架工具:

    python scripts/frontend_scaffolder.py my-app --template nextjs
    
  2. 添加可选功能(auth、api、forms、testing、storybook):

    python scripts/frontend_scaffolder.py dashboard --template nextjs --features auth,api
    
  3. 进入项目并安装依赖:

    cd my-app && npm install
    
  4. 启动开发服务器:

    npm run dev
    
脚手架选项
选项说明
--template nextjs使用 App Router 和 Server Components 的 Next.js 14+
--template react使用 TypeScript 的 React + Vite
--features auth添加 NextAuth.js 身份验证
--features api添加 React Query + API 客户端
--features forms添加 React Hook Form + Zod 校验
--features testing添加 Vitest + Testing Library
--dry-run预览将要生成的文件,但不实际创建
生成的结构(Next.js)
my-app/
├── app/
│   ├── layout.tsx        # Root layout with fonts
│   ├── page.tsx          # Home page
│   ├── globals.css       # Tailwind + CSS variables
│   └── api/health/route.ts
├── components/
│   ├── ui/               # Button, Input, Card
│   └── layout/           # Header, Footer, Sidebar
├── hooks/                # useDebounce, useLocalStorage
├── lib/                  # utils (cn), constants
├── types/                # TypeScript interfaces
├── tailwind.config.ts
├── next.config.js
└── package.json

组件生成

生成带有 TypeScript、测试和 Storybook 故事文件的 React 组件。

工作流:创建新组件
  1. 生成客户端组件:

    python scripts/component_generator.py Button --dir src/components/ui
    
  2. 生成服务端组件:

    python scripts/component_generator.py ProductCard --type server
    
  3. 生成带测试和故事文件的组件:

    python scripts/component_generator.py UserProfile --with-test --with-story
    
  4. 生成自定义 Hook:

    python scripts/component_generator.py FormValidation --type hook
    
生成器选项
选项说明
--type client带有 'use client' 的客户端组件(默认)
--type server异步服务端组件
--type hook自定义 React Hook
--with-test包含测试文件
--with-story包含 Storybook 故事
--flat在输出目录中直接创建,不建子目录
--dry-run预览但不创建文件
生成的组件示例
'use client';

import { useState } from 'react';
import { cn } from '@/lib/utils';

interface ButtonProps {
  className?: string;
  children?: React.ReactNode;
}

export function Button({ className, children }: ButtonProps) {
  return (
    <div className={cn('', className)}>
      {children}
    </div>
  );
}

包体积分析

分析 package.json 和项目结构,找出包体积优化机会。

工作流:优化包体积
  1. 在项目上运行分析工具:

    python scripts/bundle_analyzer.py /path/to/project
    
  2. 查看健康评分与问题:

    Bundle Health Score: 75/100 (C)
    
    HEAVY DEPENDENCIES:
      moment (290KB)
        Alternative: date-fns (12KB) or dayjs (2KB)
    
      lodash (71KB)
        Alternative: lodash-es with tree-shaking
    
  3. 通过替换体积较大的依赖来应用推荐的修复方案。

  4. 启用详细模式重新运行,检查导入方式:

    python scripts/bundle_analyzer.py . --verbose
    
包体积评分说明
评分等级建议操作
90-100A包体积已得到良好优化
80-89B存在一些可进行的小优化
70-79C替换体积较大的依赖
60-69D多个问题需要关注
0-59F包体积问题严重
检测到的大体积依赖

分析工具会识别以下常见的大体积包:

包名体积替代方案
moment290KBdate-fns(12KB)或 dayjs(2KB)
lodash71KB配合 Tree Shaking 使用 lodash-es
axios14KB原生 fetch 或 ky(3KB)
jquery87KB原生 DOM API
@mui/material体积较大shadcn/ui 或 Radix UI

React 模式

参考:references/react_patterns.md

复合组件

在相关组件之间共享状态:

const Tabs = ({ children }) => {
  const [active, setActive] = useState(0);
  return (
    <TabsContext.Provider value={{ active, setActive }}>
      {children}
    </TabsContext.Provider>
  );
};

Tabs.List = TabList;
Tabs.Panel = TabPanel;

// Usage
<Tabs>
  <Tabs.List>
    <Tabs.Tab>One</Tabs.Tab>
    <Tabs.Tab>Two</Tabs.Tab>
  </Tabs.List>
  <Tabs.Panel>Content 1</Tabs.Panel>
  <Tabs.Panel>Content 2</Tabs.Panel>
</Tabs>
自定义 Hook

提取可复用的逻辑:

function useDebounce<T>(value: T, delay = 500): T {
  const [debouncedValue, setDebouncedValue] = useState(value);

  useEffect(() => {
    const timer = setTimeout(() => setDebouncedValue(value), delay);
    return () => clearTimeout(timer);
  }, [value, delay]);

  return debouncedValue;
}

// Usage
const debouncedSearch = useDebounce(searchTerm, 300);
Render Props

共享渲染逻辑:

function DataFetcher({ url, render }) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetch(url).then(r => r.json()).then(setData).finally(() => setLoading(false));
  }, [url]);

  return render({ data, loading });
}

// Usage
<DataFetcher
  url="/api/users"
  render={({ data, loading }) =>
    loading ? <Spinner /> : <UserList users={data} />
  }
/>

Next.js 优化

参考:references/nextjs_optimization_guide.md

服务端组件与客户端组件

默认使用 Server Components。仅在需要以下能力时才添加 'use client':

  • 事件处理函数(onClick、onChange)
  • 状态(useState、useReducer)
  • 副作用(useEffect)
  • 浏览器 API
// Server Component (default) - no 'use client'
async function ProductPage({ params }) {
  const product = await getProduct(params.id);  // Server-side fetch

  return (
    <div>
      <h1>{product.name}</h1>
      <AddToCartButton productId={product.id} />  {/* Client component */}
    </div>
  );
}

// Client Component
'use client';
function AddToCartButton({ productId }) {
  const [adding, setAdding] = useState(false);
  return <button onClick={() => addToCart(productId)}>Add</button>;
}
图片优化
import Image from 'next/image';

// Above the fold - load immediately
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority
/>

// Responsive image with fill
<div className="relative aspect-video">
  <Image
    src="/product.jpg"
    alt="Product"
    fill
    sizes="(max-width: 768px) 100vw, 50vw"
    className="object-cover"
  />
</div>
数据获取模式
// Parallel fetching
async function Dashboard() {
  const [user, stats] = await Promise.all([
    getUser(),
    getStats()
  ]);
  return <div>...</div>;
}

// Streaming with Suspense
async function ProductPage({ params }) {
  return (
    <div>
      <ProductDetails id={params.id} />
      <Suspense fallback={<ReviewsSkeleton />}>
        <Reviews productId={params.id} />
      </Suspense>
    </div>
  );
}

无障碍与测试

参考:references/frontend_best_practices.md

无障碍检查清单
  1. 语义化 HTML:使用恰当的元素(<button>、<nav>、<main>)
  2. 键盘导航:所有交互元素都可获得焦点
  3. ARIA 标签:为图标和复杂控件提供标签
  4. 颜色对比度:普通文本的最低对比度为 4.5:1
  5. 焦点指示器:显示可见的焦点状态
// Accessible button
<button
  type="button"
  aria-label="Close dialog"
  onClick={onClose}
  className="focus-visible:ring-2 focus-visible:ring-blue-500"
>
  <XIcon aria-hidden="true" />
</button>

// Skip link for keyboard users
<a href="#main-content" className="sr-only focus:not-sr-only">
  Skip to main content
</a>
测试策略
// Component test with React Testing Library
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

test('button triggers action on click', async () => {
  const onClick = vi.fn();
  render(<Button onClick={onClick}>Click me</Button>);

  await userEvent.click(screen.getByRole('button'));
  expect(onClick).toHaveBeenCalledTimes(1);
});

// Test accessibility
test('dialog is accessible', async () => {
  render(<Dialog open={true} title="Confirm" />);

  expect(screen.getByRole('dialog')).toBeInTheDocument();
  expect(screen.getByRole('dialog')).toHaveAttribute('aria-labelledby');
});

快速参考

常见 Next.js 配置
// next.config.js
const nextConfig = {
  images: {
    remotePatterns: [{ protocol: 'https', hostname: 'cdn.example.com' }],
    formats: ['image/avif', 'image/webp'],
  },
  experimental: {
    optimizePackageImports: ['lucide-react', '@heroicons/react'],
  },
};
Tailwind CSS 工具类
// Conditional classes with cn()
import { cn } from '@/lib/utils';

<button className={cn(
  'px-4 py-2 rounded',
  variant === 'primary' && 'bg-blue-500 text-white',
  disabled && 'opacity-50 cursor-not-allowed'
)} />
TypeScript 模式
// Props with children
interface CardProps {
  className?: string;
  children: React.ReactNode;
}

// Generic component
interface ListProps<T> {
  items: T[];
  renderItem: (item: T) => React.ReactNode;
}

function List<T>({ items, renderItem }: ListProps<T>) {
  return <ul>{items.map(renderItem)}</ul>;
}

资源

  • React 模式:references/react_patterns.md
  • Next.js 优化:references/nextjs_optimization_guide.md
  • 最佳实践:references/frontend_best_practices.md
  • 强制提问库(Matt Pocock grill):references/forcing_questions.md
  • 组合映射(应分流至哪些专家):references/composition_map.md

假设与可验证的成功标准(Karpathy 准则)

在此技能搭建组件、推荐框架或审查打包产物之前,必须明确提出以下四项假设。

  1. 主要用户设备 + 网络 — 移动设备 + 4G、桌面设备 + 光纤网络、低端 Android 设备或企业网络。所有性能决策都取决于此。
  2. LCP 目标(毫秒) — 必须是一个具体数字,而不是“快”。它决定打包预算和渲染方式。
  3. 依赖 SEO 还是受身份验证保护 — 它决定渲染方式(SSR/SSG/RSC 或 SPA)。
  4. WCAG 目标 + 指定的无障碍负责人 — AA、AAA 或尽力而为。它决定无障碍投入和 CI 门禁。

可验证的成功标准(Karpathy #4)——每项建议都必须包含:

  • 主要设备上 p75 的 Core Web Vitals 目标(LCP、INP、CLS)
  • 每条路由以 KB-gzip 为单位的 JS 打包预算
  • Lighthouse 无障碍底线 + 性能底线

如果未说明上述三项中的任何一项,该建议就不完整——请返回强制提问库中的 Q2。

scripts/frontend_decision_engine.py 工具会对这些检查进行编码:如果未提供四项假设输入,它将拒绝推荐配置文件,并输出与匹配配置文件对应的可验证阈值。


自定义配置文件

profiles/ 中内置的四种配置文件会对所有建议进行校准:

配置文件适用场景LCP 目标(移动设备 + 4G,p75)打包预算
next-app-router面向客户的 SaaS,兼顾 SEO 和动态内容,优先采用 RSC2000ms每条路由 150 KB-gzip
remix-or-sveltekit主要面向移动设备 + 4G,优先减少 JS,渐进增强1500ms每条路由 80 KB-gzip
vite-spa受身份验证保护的应用,主要面向桌面设备 / 企业网络2500ms初始化 200 KB + 每条路由 80 KB
astro-or-static营销页面 / 文档 / 博客,几乎没有写入操作,SEO 至关重要1200ms每页 30 KB JS

通过以下方式选择配置文件:

python scripts/frontend_decision_engine.py \
  --primary-device mobile-4g --lcp-target-ms 2000 \
  --seo-dependent true --auth-walled false --team-size 5

该工具会返回最匹配的配置文件、候选配置(如果差异在 15% 以内)、技术栈选择、该配置应避免的反模式,以及必需的 CI 门禁。

要添加自定义配置文件(例如,贵组织针对内部工具的默认配置):将 profiles/vite-spa.json 复制到 profiles/<your-org>.json,然后调整 constraints + success_thresholds。


组合映射

此技能不会重新实现由 POWERFUL 层级的专家负责的范围,而是将任务分流给他们。完整的路由表请参阅 references/composition_map.md。主要分流路径如下:

关注点分流至
WCAG 审核、对比度、屏幕阅读器engineering-team/skills/a11y-audit/
打包产物分析 + 运行时性能engineering/skills/performance-profiler/
电影感 / 滚动叙事式落地页engineering-team/skills/epic-design/
Apple HIG(iOS / macOS / visionOS)product-team/skills/apple-hig-expert/
提交前 Karpathy 审查engineering/karpathy-coder/
预检架构审查engineering/grill-me/

cs-frontend-engineer Agent 通过 context: fork 协调这些分流。可从另一个 Agent 调用它:Agent({subagent_type: "cs-frontend-engineer", prompt: "..."}),或通过 /cs-frontend-review <your problem> 调用。


强制提问库(Matt Pocock 拷问)

在敲定任何框架或渲染方案前,逐一提出 references/forcing_questions.md 中的七个强制问题。要求:

  1. 每轮只问一个问题。不得合并提问。
  2. 始终给出有权威依据支持的答案建议。
  3. 将答案记录在 /tmp/frontend-grill-<date>.md 中。
  4. 如果触发了否决条件,立即停止。不要围绕尚未解决的缺口搭建框架。
  5. 问完第 7 个问题后,使用这七个答案运行 frontend_decision_engine.py。

概要:

  1. 主要设备和网络是什么?
  2. LCP 目标是多少毫秒(以及 INP、CLS)?
  3. 选择 RSC、SPA、SSR 还是 SSG?并说明理由。
  4. 每个路由的 JS 包预算是多少?
  5. 是否依赖 SEO,或有身份验证墙?
  6. 设计系统的唯一事实来源是什么?
  7. WCAG 目标是什么?指定的无障碍负责人是谁?

其他 Agent 和技能的调用方式

三种方式:

  1. 斜杠命令: /cs-frontend-review <prompt> — 完整的强制提问流程、决策引擎和组合路由。
  2. Agent 子 Agent: Agent({subagent_type: "cs-frontend-engineer", prompt: "..."}) — 分叉上下文,返回不超过 200 词的摘要。
  3. 直接调用工具: python scripts/frontend_decision_engine.py ... — 在已知输入的情况下进行确定性配置匹配。

完整的调用约定请参阅 agents/engineering/cs-frontend-engineer.md。

评论

支持 Markdown