mcpField
S
senior-frontend

senior-frontend

github.com/sickn33开发49.1k269 次安装今天更新
代码仓库

关于 senior-frontend

senior-frontend 是面向 React 和 Next.js 开发者的前端技能,涵盖应用构建与审查。它结合项目和组件生成器、包体积分析、优化建议、无障碍检查及测试实践。

主要功能

  1. 01React 和 Next.js 项目脚手架
  2. 02生成 TypeScript 组件和 Hook
  3. 03包体积分析与建议
  4. 04React 和 Next.js 模式指导
  5. 05无障碍与测试清单

适用场景

  1. 01搭建 React 或 Next.js 应用
  2. 02生成带测试或 Storybook 的组件
  3. 03查找项目中的大型依赖
  4. 04检查无障碍设计和前端测试

安装

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

$npx skills add https://github.com/sickn33/agentic-awesome-skills --skill senior-frontend

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

包含的文件

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

references/
frontend_best_practices.md
nextjs_optimization_guide.md
react_patterns.md
scripts/
component_generator.py
bundle_analyzer.py
frontend_scaffolder.py

详细介绍

高级前端

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

适用场景

  • 使用 TypeScript 和 Tailwind CSS 搭建新的 React 或 Next.js 项目时。
  • 生成新组件或自定义 Hook 时。
  • 分析和优化前端应用的打包体积时。
  • 实现或审查 Compound Components、Render Props 等高级 React 模式时。
  • 确保符合无障碍标准并实施完善的测试策略时。

目录


项目搭建

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

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

    python scripts/frontend_scaffolder.py my-app --template nextjs
    
  2. 添加可选功能(身份验证、API、表单、测试、Storybook):

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

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

    npm run dev
    
脚手架选项
选项说明
--template nextjsNext.js 14+,采用 App Router 和 Server Components
--template reactReact + Vite,使用 TypeScript
--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

服务端组件与客户端组件

默认使用服务端组件。仅在需要以下功能时添加 '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: [{ 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

限制

  • 仅当任务明确符合上述范围时,才使用此技能。
  • 不要将输出视为环境特定验证、测试或专家审查的替代品。
  • 如果缺少必需的输入、权限、安全边界或成功标准,请停止并请求澄清。

快照限制

示例仅为摘录,不代表通过生产环境认证。脚手架依赖面向历史版本 Next14/React18/Tailwind3,安装前需要制定受支持且已修补的依赖方案。可选脚手架功能模板并不完整,目前会拒绝生成。生成的 React/Vite 配置需要匹配的别名、TSX 和 lint 设置;身份验证需要由服务器强制执行,而不能依赖前端 HOC。组件/测试假设应用已配置相关导入、样式和测试固定数据。软件包体积评分和 KB 表格仅为参考性启发指标,并非实测结果,也不能作为自动替换软件包的依据。

客户端组件可以在服务器上预渲染:localStorage 初始化程序可能导致水合不匹配;应在挂载后读取,并设置加载边界和处理错误/键变更。useAsync/DataFetcher 示例需要加入取消、过期响应和错误处理。自定义 select/dialog 示例未涵盖完整的键盘操作、焦点恢复和背景 inert 行为;请优先使用经过测试的基础组件。不要在 localStorage 中持久化承载者令牌,退出登录时清除会话数据,并在 API 路由中强制执行授权。没有按用户/租户划分的键时,切勿共享个性化缓存数据。请根据已安装的 Next 版本匹配 params、fetch 缓存、revalidateTag、Image preload 和动态 SSR API。

评论

支持 Markdown