Back to Blog
vibcoding Team5 分で読めます

Next.js 15 性能优化实战:从 5s 到 1s 的加载提升

深入分析 Next.js 15 性能优化策略,包括 Server Components、Streaming、缓存策略和代码分割,附真实优化案例。

#Next.js#性能优化#React#Web开发#前端
Next.js 15 性能优化实战:从 5s 到 1s 的加载提升

Next.js 15 性能优化实战:从 5s 到 1s 的加载提升

问题背景

我们的 AI 工具网站使用 Next.js 15 构建,上线后发现首屏加载时间高达 5.5 秒,用户体验极差。

Speed Insights 诊断结果:

  • TTFB: 5.5s ❌
  • FCP: 6.68s ❌
  • LCP: 6.68s ❌
  • Real Experience Score: 37 ❌

经过一系列优化后:

  • TTFB: 0.8s ✅
  • FCP: 1.2s ✅
  • LCP: 1.5s ✅
  • Real Experience Score: 92 ✅

下面分享完整的优化过程。

第一步:分析问题根源

使用浏览器 DevTools Network 面板发现:

  1. 页面加载时发起 20+ 个 API 请求
  2. 巨大的 JavaScript bundle (2.5MB)
  3. 未优化的图片 (每张 500KB+)
  4. 大量 307 重定向

第二步:优化 Server Components

之前(问题代码)

tsx
// ❌ 在客户端组件中获取数据
'use client';

export default function Dashboard() {
  const [data, setData] = useState(null);
  
  useEffect(() => {
    // 这会导致客户端请求,增加 TTFB
    fetch('/api/stats').then(r => r.json()).then(setData);
  }, []);
  
  return <div>{data ? <Stats data={data} /> : <Loading />}</div>;
}

之后(优化后)

tsx
// ✅ 使用 Server Component 直接获取数据
async function Dashboard() {
  // 数据在服务端获取,直接渲染 HTML
  const data = await fetchStats();
  
  return <Stats data={data} />;
}

// 交互组件单独抽离
'use client';
function InteractiveChart({ data }) {
  // 只有需要交互的部分才是客户端组件
  return <Chart data={data} onClick={...} />;
}

效果: TTFB 从 5.5s 降到 1.2s

第三步:实现 Streaming

tsx
// app/dashboard/page.tsx
import { Suspense } from 'react';

export default function DashboardPage() {
  return (
    <div>
      {/* 立即显示的静态内容 */}
      <Header />
      
      {/* 慢数据使用 Suspense 包裹 */}
      <Suspense fallback={<StatsSkeleton />}>
        <Stats />
      </Suspense>
      
      <Suspense fallback={<ChartSkeleton />}>
        <Charts />
      </Suspense>
      
      <Suspense fallback={<TableSkeleton />}>
        <RecentActivity />
      </Suspense>
    </div>
  );
}

效果: FCP 从 6.68s 降到 1.5s(骨架屏立即显示)

第四步:优化代码分割

动态导入重型组件

tsx
import dynamic from 'next/dynamic';

// 重型图表库延迟加载
const HeavyChart = dynamic(
  () => import('@/components/HeavyChart'),
  { 
    loading: () => <ChartSkeleton />,
    ssr: false 
  }
);

// Monaco 编辑器延迟加载
const CodeEditor = dynamic(
  () => import('@monaco-editor/react'),
  { 
    loading: () => <div className="h-96 bg-gray-100 animate-pulse" />,
    ssr: false 
  }
);

next.config.mjs 优化

javascript
export default {
  experimental: {
    optimizePackageImports: [
      '@radix-ui/react-icons',
      'framer-motion',
      'lucide-react',
    ],
  },
  
  // 生产环境移除 console.log
  compiler: {
    removeConsole: process.env.NODE_ENV === 'production'
      ? { exclude: ['error', 'warn'] }
      : false,
  },
};

效果: JS Bundle 从 2.5MB 降到 800KB

第五步:禁用不必要的预取

tsx
// 导航链接禁用预取
<Link href="/dashboard" prefetch={false}>
  Dashboard
</Link>

// 或者在 next.config.mjs 全局配置
experimental: {
  // 只在 hover 时预取
  linkPrefetch: 'intent',
}

效果: 减少 80% 的不必要请求

第六步:图片优化

tsx
import Image from 'next/image';

// ✅ 使用 next/image 自动优化
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={630}
  priority // 首屏图片使用 priority
  placeholder="blur"
  blurDataURL="data:image/jpeg;base64,..."
/>

next.config.mjs 图片配置

javascript
images: {
  formats: ['image/avif', 'image/webp'],
  deviceSizes: [640, 750, 828, 1080, 1200, 1920],
  minimumCacheTTL: 31536000, // 1年缓存
},

效果: 图片体积减少 70%

第七步:缓存策略

页面级缓存

tsx
// 静态页面启用 ISR
export const revalidate = 3600; // 1小时重新验证

// 动态页面使用 unstable_cache
import { unstable_cache } from 'next/cache';

const getCachedStats = unstable_cache(
  async () => {
    return await db.query('SELECT ...');
  },
  ['stats'],
  { revalidate: 60 }
);

HTTP 缓存头

javascript
// next.config.mjs
async headers() {
  return [
    {
      source: '/_next/static/:path*',
      headers: [
        { key: 'Cache-Control', value: 'public, max-age=31536000, immutable' },
      ],
    },
  ];
}

最终成果

指标 优化前 优化后 提升
TTFB 5.5s 0.8s 85%
FCP 6.68s 1.2s 82%
LCP 6.68s 1.5s 78%
JS Bundle 2.5MB 800KB 68%
Score 37 92 149%

检查清单

  • Server Components 处理数据获取
  • Suspense 包裹慢组件
  • 动态导入重型组件
  • 禁用不必要的 Link prefetch
  • 使用 next/image 优化图片
  • 配置适当的缓存策略
  • 移除生产环境的 console.log

总结

Next.js 15 提供了强大的性能优化工具,但需要正确使用:

  1. Server Components First - 尽可能在服务端处理数据
  2. Progressive Loading - 使用 Suspense 实现渐进式加载
  3. Lazy Everything - 非首屏内容全部延迟加载
  4. Cache Aggressively - 能缓存的都缓存

性能优化是持续的过程,建议定期使用 Vercel Speed Insights 或 Lighthouse 监控。


更多优化技巧欢迎在 GitHub 讨论!

v
vibcoding Team
vibcoding Tech Team
Found this helpful? Share it!