Next.js15OptimizationSkill nextjs-optimization

这个技能专注于优化 Next.js 15 应用程序,以提升网站性能,核心 Web 指标得分,以及遵循生产最佳实践。关键词包括:性能优化、核心 Web 指标、SEO、React、App Router。

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

Next.js 15 优化技能

目标

优化 Next.js 应用程序以实现:

  • 完美的核心 Web 指标得分(LCP < 2.5s, FID < 100ms, CLS < 0.1)
  • 快速的页面加载时间和最优的渲染策略
  • 高效的数据获取和缓存
  • 生产就绪的构建配置
  • SEO 和无障碍卓越

何时使用此技能

自动调用时:

  • 项目使用 Next.js(通过 next 在依赖项中检测)
  • 用户提到“优化”,“性能”,“慢”或“核心 Web 指标”
  • 生产部署前
  • 添加新功能或页面后
  • 用户请求 Next.js 特定的改进

先决条件检查

工具:读取,搜索

  1. 验证 Next.js 版本

    # 读取 package.json
    # 检查 "next": "^15.0.0" 或更高版本
    
  2. 检测 App Router(Next.js 13+):

    • 检查 app/ 目录
    • 检查 layout.tsx, page.tsx 文件
  3. 检测页面路由器(遗留):

    • 检查 pages/ 目录
    • 建议迁移到 App Router

优化类别

1. 渲染策略优化

目标:为每个页面/组件选择最优的渲染

工具:读取,搜索,编辑

1.1 服务器组件(App Router 默认)

何时使用

  • 从 API/数据库获取数据
  • 重计算
  • 访问后端资源

模式

// app/dashboard/page.tsx
export default async function DashboardPage() {
  const data = await fetchData(); // 在服务器上运行
  return <Dashboard data={data} />;
}

检查违规

# 在不需要的组件中搜索 "use client"
grep -r "use client" app/ | grep -v "onClick\|useState\|useEffect"

1.2 客户端组件

何时使用

  • 交互式 UI(onClick, 表单)
  • 浏览器 API(window, localStorage)
  • React 钩子(useState, useEffect)

模式

// app/components/Counter.tsx
'use client';

export default function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>{count}</button>;
}

优化:保持客户端组件小而叶节点

1.3 静态生成(SSG)

何时使用

  • 很少变化的内容
  • 营销页面,博客,文档

模式

export const revalidate = 3600; // 每小时重新验证一次

export default async function BlogPost({ params }) {
  const post = await getPost(params.slug);
  return <Article post={post} />;
}

1.4 动态渲染与 ISR

何时使用

  • 定期变化的内容
  • 电子商务产品,用户配置文件

模式

export const revalidate = 60; // 每分钟重新验证一次

export async function generateStaticParams() {
  const products = await getProducts();
  return products.map((p) => ({ slug: p.slug }));
}

2. 图像优化

目标:优化图像以提高性能和核心 Web 指标

工具:搜索,读取,编辑

2.1 使用 Next.js 图像组件

查找未优化的图像

grep -rn "<img " app/ src/

替换为

import Image from 'next/image';

<Image
  src="/hero.jpg"
  alt="Hero image"
  width={1200}
  height={600}
  priority // 对于页面上方的图像
  placeholder="blur" // 可选的模糊效果
/>

2.2 配置图像域

读取 next.config.js

module.exports = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
      },
    ],
    formats: ['image/avif', 'image/webp'], // 现代格式
  },
};

2.3 延迟加载策略

  • priority:页面上方的图像(LCP 候选)
  • loading=“lazy”:页面下方的图像(默认)

3. 字体优化

目标:消除 FOUT/FOIT 并改善字体加载

工具:读取,编辑

3.1 使用 next/font

模式

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

const inter = Inter({
  subsets: ['latin'],
  display: 'swap', // 防止 FOIT
  variable: '--font-inter',
});

export default function RootLayout({ children }) {
  return (
    <html lang="en" className={inter.variable}>
      <body>{children}</body>
    </html>
  );
}

3.2 自托管字体

import localFont from 'next/font/local';

const customFont = localFont({
  src: './fonts/CustomFont.woff2',
  display: 'swap',
  variable: '--font-custom',
});

4. 数据获取优化

目标:最小化瀑布流并优化缓存

工具:读取,搜索,编辑

4.1 并行数据获取

反模式(顺序):

const user = await getUser();
const posts = await getPosts(user.id); // 等待用户

优化(并行):

const [user, posts] = await Promise.all([
  getUser(),
  getPosts(),
]);

4.2 流式传输与 Suspense

模式

import { Suspense } from 'react';

export default function Page() {
  return (
    <>
      <Header />
      <Suspense fallback={<Skeleton />}>
        <SlowComponent />
      </Suspense>
      <Footer />
    </>
  );
}

4.3 缓存配置

// 积极缓存
fetch('https://api.example.com/data', {
  next: { revalidate: 3600 }, // 缓存 1 小时
});

// 无缓存
fetch('https://api.example.com/data', {
  cache: 'no-store', // 总是新鲜的
});

// 退出缓存
export const dynamic = 'force-dynamic';

5. 捆绑优化

目标:减少 JavaScript 捆绑包大小

工具:Bash,读取,编辑

5.1 分析捆绑包

# 添加到 package.json 脚本
npm run build
npx @next/bundle-analyzer

5.2 动态导入

查找大组件

find app -name "*.tsx" -exec wc -l {} \; | sort -rn | head -10

用动态导入拆分

import dynamic from 'next/dynamic';

const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
  loading: () => <Skeleton />,
  ssr: false, // 如果不需要则跳过 SSR
});

5.3 树摇动

检查桶导出

grep -rn "export \* from" app/

替换为特定导入

// 反模式
import { Button, Card, Modal } from '@/components';

// 优化
import { Button } from '@/components/Button';

6. 元数据和 SEO

目标:完美的 SEO 和社交分享

工具:读取,编辑

6.1 静态元数据

// app/layout.tsx
export const metadata = {
  title: {
    default: 'My App',
    template: '%s | My App',
  },
  description: 'Description for SEO',
  openGraph: {
    title: 'My App',
    description: 'Description for social sharing',
    images: ['/og-image.jpg'],
  },
  twitter: {
    card: 'summary_large_image',
  },
};

6.2 动态元数据

export async function generateMetadata({ params }) {
  const post = await getPost(params.slug);
  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      images: [post.ogImage],
    },
  };
}

7. 生产配置

目标:为生产优化 next.config.js

工具:读取,编辑

7.1 基本配置

// next.config.js
module.exports = {
  reactStrictMode: true,
  poweredByHeader: false, // 安全
  compress: true, // Gzip 压缩
  
  // 编译器优化
  compiler: {
    removeConsole: process.env.NODE_ENV === 'production',
  },
  
  // 图像优化
  images: {
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920],
  },
  
  // React 编译器(Next.js 15)
  experimental: {
    reactCompiler: true,
  },
};

7.2 Turbopack(开发)

// package.json
{
  "scripts": {
    "dev": "next dev --turbo"
  }
}

8. 核心 Web 指标优化

目标:实现完美的 Lighthouse 得分

工具:Bash,搜索,编辑

8.1 LCP(最大内容绘制)< 2.5s

优化

  • 使用 priority 对英雄图像
  • 预加载关键资源
  • 服务器端渲染页面上方的内容
// 预加载关键资源
<link rel="preload" href="/hero.jpg" as="image" />

8.2 FID(首次输入延迟)< 100ms

优化

  • 最小化 JavaScript 执行
  • 为非关键代码使用动态导入
  • 延迟第三方脚本
import Script from 'next/script';

<Script
  src="https://analytics.example.com"
  strategy="lazyOnload" // 页面交互后加载
/>

8.3 CLS(累积布局偏移)< 0.1

优化

  • 始终指定图像尺寸
  • 为动态内容预留空间
  • 使用 font-display: swap
/* 为广告/横幅预留空间 */
.ad-container {
  min-height: 250px;
}

9. 缓存策略

目标:最大化缓存命中并最小化服务器负载

工具:读取,编辑

9.1 路由段配置

// app/dashboard/page.tsx
export const revalidate = 3600; // ISR 每小时
export const dynamic = 'auto'; // 自动优化
export const fetchCache = 'force-cache'; // 积极缓存

9.2 数据缓存

// 自动去重和缓存
const user = await fetch('https://api.example.com/user');

// 基于标签重新验证
export const revalidate = 60;
export const tags = ['user', 'profile'];

10. 监控和测量

目标:随时间跟踪性能

工具:Bash,网络搜索

10.1 添加 Web 指标报告

// app/layout.tsx
import { SpeedInsights } from '@vercel/speed-insights/next';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <SpeedInsights />
      </body>
    </html>
  );
}

10.2 Lighthouse CI

# 运行 Lighthouse
npx lighthouse http://localhost:3000 --view

# 检查核心 Web 指标
npm run build
npm run start
npx lighthouse http://localhost:3000 --only-categories=performance

优化清单

运行此清单

  • [ ] 所有图像使用 next/image 并具有适当的尺寸
  • [ ] 字体使用 next/font 并具有 display: swap
  • [ ] 默认使用服务器组件(无不必要的 ‘use client’)
  • [ ] 客户端组件是叶节点且最小化
  • [ ] 数据获取尽可能使用并行请求
  • [ ] 慢速组件用 <Suspense> 包装
  • [ ] 大型组件使用动态导入
  • [ ] 为所有页面配置元数据
  • [ ] next.config.js 具有生产优化
  • [ ] 启用 React 编译器(Next.js 15)
  • [ ] 分析并优化捆绑包
  • [ ] 核心 Web 指标达到目标(使用 Lighthouse 测试)

输出格式

# Next.js 优化报告

## 当前状态
- **Next.js 版本**:15.0.3
- **渲染**:App Router
- **React 版本**:19.0.0

## 发现的问题

### 🔴 严重(3)
1. **未优化的图像**:发现 12 个 `<img>` 标签
   - 文件:`app/page.tsx`, `app/about/page.tsx`
   - 修复:替换为 `next/image`

2. **大型客户端捆绑包**:342 KB(目标:< 200 KB)
   - 原因:同步加载重型图表库
   - 修复:对 `Chart` 组件使用动态导入

3. **缺少字体优化**:通过 <link> 使用 Google 字体
   - 修复:迁移到 `next/font/google`

### 🟡 警告(2)
1. **顺序数据获取**:在 `app/dashboard/page.tsx` 中检测到瀑布流
2. **无元数据**:5 个页面缺少 OpenGraph 标签

## 应用的优化

✅ 在 next.config.js 中启用 React 编译器
✅ 添加图像优化配置
✅ 配置适当的缓存头
✅ 向慢速路由添加 Suspense 边界

## 性能影响(估计)

- **加载时间**:3.2s → 1.8s(-44%)
- **捆绑包大小**:342 KB → 198 KB(-42%)
- **LCP**:3.1s → 2.3s(✅ 良好)
- **FID**:85ms → 45ms(✅ 良好)
- **CLS**:0.15 → 0.05(✅ 良好)

## 下一步

1. 替换 12 个 `<img>` 标签为 `next/image`
2. 使用动态导入拆分图表组件
3. 为 5 个页面添加元数据
4. 运行 Lighthouse 以验证改进