Next.js 预渲染完全指南:SSG vs SSR,看完秒懂!

如何让你的 Next.js 应用秒开?预渲染机制是关键!本文将带你彻底搞懂两种预渲染方式的区别和实战应用。

前言:为什么需要预渲染?

大家好,我是前端大鱼。最近在自己的项目中深度使用了 Next.js,不得不说它的预渲染能力真的太香了!

想象一下这样的场景:用户打开你的网站,几乎瞬间看到完整内容,而不是先看一个 loading 动画等待几秒钟。这就是预渲染带来的魔力!

与传统 React SPA 相比,Next.js 的预渲染让 SEO 再也不是问题,搜索引擎爬虫可以直接看到完整的页面内容。今天我就带大家彻底搞懂 Next.js 的预渲染机制。

一、预渲染的两种方式

1.1 静态生成(SSG)- 推荐首选

构建时生成页面,直接输出 HTML 文件扔到 CDN 上。

jsx 复制代码
export default function HomePage({ posts }) {
  return (
    <div>
      <h1>博客首页</h1>
      {posts.map(post => (
        <Article key={post.id} post={post} />
      ))}
    </div>
  );
}

export async function getStaticProps() {
  const res = await fetch('https://api.example.com/posts');
  const posts = await res.json();

  return {
    props: { posts }, // 传递给页面组件
    revalidate: 60,   // 60秒后可重新生成(ISR)
  };
}

优点

  • ⚡️ 速度极致:CDN 直接返回静态文件,快就一个字
  • 💰 成本极低:不需要服务器实时计算
  • 🔍 SEO 友好:内容完整可抓取
  • 🚀 高并发:轻松应对流量高峰

适用场景

  • 博客、文档站
  • 电商商品列表页
  • 公司官网
  • 营销落地页

1.2 服务器端渲染(SSR)- 按需使用

每次请求时生成页面,适合个性化内容。

jsx 复制代码
export default function UserProfile({ user }) {
  return (
    <div>
      <h1>欢迎, {user.name}!</h1>
      <p>这是你的个人主页</p>
    </div>
  );
}

// 每次请求都运行
export async function getServerSideProps(context) {
  // 获取 cookies 验证用户
  const token = context.req.cookies.auth;
  const user = await fetchUser(token);

  if (!user) {
    return {
      redirect: {
        destination: '/login', // 未登录跳转
        permanent: false,
      },
    };
  }

  return {
    props: { user }, // 传递给页面
  };
}

优点

  • 📊 数据实时:每次都是最新数据
  • 👤 个性化:基于用户请求定制内容
  • 🔐 安全性:敏感数据处理在服务端

适用场景

  • 用户仪表盘
  • 实时数据页面
  • 需要权限验证的页面

二、动态路由的预渲染技巧

对于动态路由(如 /posts/[id].js),需要 getStaticPaths 配合:

jsx 复制代码
// pages/posts/[id].js
export default function PostDetail({ post }) {
  return <Article content={post.content} />;
}

// 告诉 Next.js 哪些路径需要预渲染
export async function getStaticPaths() {
  const posts = await fetch('https://api.example.com/posts');
  
  const paths = posts.map(post => ({
    params: { id: post.id.toString() },
  }));

  return {
    paths,
    fallback: 'blocking', // 重要参数!
  };
}

// 获取具体数据
export async function getStaticProps({ params }) {
  const post = await fetchPost(params.id);
  
  return {
    props: { post },
    revalidate: 3600, // 每小时更新一次
  };
}

fallback 参数详解

  • false:只渲染指定路径,其他 404
  • true:先返回降级页面,后台生成新页面
  • 'blocking':等待生成完成再返回,用户体验更好

三、实战选择指南

3.1 如何选择?

根据你的业务场景来定:

用 SSG(静态生成)如果:

  • 内容不经常变化
  • 需要极致的性能
  • 页面是公开的,不需要用户验证

用 SSR(服务器端渲染)如果:

  • 数据实时性要求高
  • 内容高度个性化
  • 需要访问请求上下文(如 cookies)

3.2 性能对比

指标 SSG SSR
加载速度 ⭐⭐⭐⭐⭐ ⭐⭐⭐
SEO 支持 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
实时性 ⭐⭐(可配 ISR) ⭐⭐⭐⭐⭐
服务器压力 ⭐⭐⭐⭐⭐ ⭐⭐⭐
开发复杂度 ⭐⭐⭐ ⭐⭐⭐⭐

3.3 混合使用案例

在实际项目中,我们通常混合使用:

jsx 复制代码
// 主页:SSG + 客户端数据获取
export default function Home({ initialData }) {
  const [realTimeData, setRealTimeData] = useState(null);
  
  // 静态部分优先展示
  // 动态部分客户端获取
  useEffect(() => {
    fetchRealTimeData().then(setRealTimeData);
  }, []);

  return (
    <div>
      <StaticContent data={initialData} />
      {realTimeData && <DynamicContent data={realTimeData} />}
    </div>
  );
}

export async function getStaticProps() {
  const initialData = await fetchInitialData();
  return { props: { initialData }, revalidate: 60 };
}

四、最佳实践与坑点避雷

4.1 一定要知道的坑

坑1:getStaticPaths 的 fallback 选择

jsx 复制代码
// 错误:大量动态页面时用 false
return { paths: [], fallback: false };

// 正确:用 blocking 或 true
return { paths: [], fallback: 'blocking' };

坑2:API 路由不匹配

jsx 复制代码
// 错误:在 getStaticProps 里调用了内部 API
const res = await fetch('http://localhost:3000/api/posts');

// 正确:直接导入函数或调用外部 API
const posts = await getPostsFromDB();

4.2 性能优化技巧

1. 使用 ISR(增量静态再生)

jsx 复制代码
export async function getStaticProps() {
  return {
    props: { /* ... */ },
    revalidate: 60, // 60秒后可重新生成
  };
}

2. 优化图片加载

jsx 复制代码
import Image from 'next/image';

export default function Product({ product }) {
  return (
    <div>
      <Image
        src={product.image}
        alt={product.name}
        width={500}
        height={300}
        placeholder="blur" // 占位优化
      />
    </div>
  );
}

3. 代码分割自动完成 Next.js 自动按页面做代码分割,无需额外配置!

五、总结

Next.js 的预渲染机制是其最大亮点之一,正确使用能让你的应用性能飞起:

  1. SSG 用于静态内容 - 极致性能,CDN 友好
  2. SSR 用于动态内容 - 实时数据,个性化强
  3. 混合使用更灵活 - 根据不同场景选择方案
  4. ISR 平衡两者 - 静态生成 + 定时更新

掌握了这些,你就能充分发挥 Next.js 的优势,打造出高性能的 React 应用!


互动时间:大家在用 Next.js 时遇到过哪些预渲染的问题?欢迎在评论区分享你的经验和疑问!

关注公众号" 大前端历险记",掌握更多前端开发干货姿势!

相关推荐
月出3 小时前
无限循环滚动条 - 左出右进
前端
aiwery3 小时前
实现带并发限制的 Promise 调度器
前端·算法
熊猫片沃子3 小时前
浅谈Vue 响应式原理
前端
货拉拉技术3 小时前
微前端中的错误堆栈问题探究
前端·javascript·vue.js
前端老鹰3 小时前
HTML `<datalist>`:原生下拉搜索框,无需 JS 也能实现联想功能
前端·css·html
南北是北北3 小时前
Android TexureView和SurfaceView
前端·面试
code_YuJun3 小时前
脚手架架构设计
前端
pepedd8644 小时前
WebAssembly简单入门
前端·webassembly·trae
ze_juejin4 小时前
JavaScript 的基本数据类型
前端