前端卓越 frontend-excellence

该技能专注于现代前端开发的最佳实践,涵盖使用React Server Components进行服务器端渲染、性能优化技术如代码分割和捆绑优化,以及优化Core Web Vitals指标(如LCP、INP、CLS)以提升网站性能和用户体验。适用于React、Next.js等框架,关键词:前端开发、React Server Components、性能优化、Core Web Vitals、代码分割、图像优化、字体加载、CLS预防。

前端开发 0 次安装 0 次浏览 更新于 3/8/2026

name: 前端卓越 description: 用于React Server Components、性能优化和Core Web Vitals的现代前端模式

前端卓越

React Server Components

服务器组件在服务器上运行,并将渲染的HTML发送到客户端。它们可以直接访问数据库、文件系统和内部API,而无需将其暴露给浏览器。

// app/products/page.tsx (默认是服务器组件)
async function ProductsPage() {
  const products = await db.query("SELECT * FROM products WHERE active = true");
  return (
    <main>
      <h1>Products</h1>
      <ProductList products={products} />
      <AddToCartButton />  {/* 客户端组件 */}
    </main>
  );
}

规则:

  • 服务器组件不能使用 useStateuseEffect 或浏览器API
  • 在文件顶部用 'use client' 标记交互组件
  • 从服务器组件传递可序列化的props到客户端组件(不能传递函数或类)
  • 尽量将 'use client' 边界保持在树中尽可能深的位置

Streaming SSR

import { Suspense } from 'react';

export default function Dashboard() {
  return (
    <div>
      <Header />  {/* 立即渲染 */}
      <Suspense fallback={<ChartSkeleton />}>
        <AnalyticsChart />  {/* 准备好时流式传输 */}
      </Suspense>
      <Suspense fallback={<TableSkeleton />}>
        <RecentOrders />  {/* 独立流式传输 */}
      </Suspense>
    </div>
  );
}

每个 Suspense 边界独立流式传输。将边界放在数据获取组件周围,以避免阻塞整个页面。

代码分割

import dynamic from 'next/dynamic';

const HeavyEditor = dynamic(() => import('@/components/Editor'), {
  loading: () => <EditorSkeleton />,
  ssr: false,
});

const AdminPanel = dynamic(() => import('@/components/AdminPanel'));

分割点:

  • 路由边界(Next.js App Router 中自动)
  • 条件渲染的组件(模态框、抽屉、管理面板)
  • 重型库(图表库、富文本编辑器、地图)
  • 首屏下方内容

捆绑优化

// next.config.js
module.exports = {
  experimental: {
    optimizePackageImports: ['lucide-react', '@heroicons/react', 'lodash-es'],
  },
};

检查清单:

  • 运行 npx next build 并查看每个路由的输出大小
  • 使用 @next/bundle-analyzer 识别大型依赖
  • date-fnsdayjs 替换 moment(节省约200KB)
  • 导入特定函数:import { debounce } from 'lodash-es/debounce'
  • 优先使用CSS而非JS进行动画(无运行时成本)
  • 树摇图标库:import { Search } from 'lucide-react'

Core Web Vitals 目标

指标 良好 需要改进
LCP (最大内容绘制) <2.5秒 2.5-4.0秒 >4.0秒
INP (交互到下一次绘制) <200毫秒 200-500毫秒 >500毫秒
CLS (累计布局偏移) <0.1 0.1-0.25 >0.25

LCP 优化

  • 预加载英雄图片:<link rel="preload" as="image" href="..." />
  • 在首屏 <Image> 组件上使用 priority 属性
  • 内联关键CSS,延迟非关键样式表
  • 为首屏内容避免客户端渲染
  • 在图片上设置显式的 width/height 以防止布局偏移

图像优化

import Image from 'next/image';

<Image
  src="/hero.jpg"
  alt="描述性替代文本"
  width={1200}
  height={630}
  priority              // 为LCP图片预加载
  sizes="(max-width: 768px) 100vw, 50vw"
  placeholder="blur"
  blurDataURL={base64}  // 内联微小占位符
/>
  • 使用 next/image 或等效库(自动WebP/AVIF,响应式srcset)
  • 设置 sizes 属性以避免下载过大的图片
  • 使用 placeholder="blur" 与base64数据URL以提升感知性能
  • 延迟加载首屏下方图片(默认行为)

字体加载策略

// app/layout.tsx
import { Inter } from 'next/font/google';

const inter = Inter({
  subsets: ['latin'],
  display: 'swap',       // 立即显示后备字体
  preload: true,
  variable: '--font-inter',
});

export default function RootLayout({ children }) {
  return (
    <html className={inter.variable}>
      <body>{children}</body>
    </html>
  );
}
  • 使用 next/font 进行零CLS字体加载,带自动子集
  • 设置 display: 'swap' 以避免加载期间文本不可见
  • 自托管字体而非从Google CDN加载(节省DNS查找)
  • 最多限制为2个字体族

CLS 预防

  • 始终在图片和视频上设置 widthheight
  • 使用 aspect-ratio CSS 用于响应式媒体容器
  • 为动态内容(广告、嵌入)预留空间,使用 min-height
  • 避免在加载后向现有内容上方插入内容
  • 使用CSS contain: layout 用于改变大小的组件

性能监控

import { onCLS, onINP, onLCP } from 'web-vitals';

onCLS(console.log);
onINP(console.log);
onLCP(console.log);

测量真实用户指标(RUM),而不仅仅是实验室分数。Vercel Analytics 和 Google Search Console 提供现场数据。