Next.js的静态生成和服务端渲染,你搞懂了吗?

Next.js的静态生成和服务端渲染,你搞懂了吗?

嘿,各位前端小伙伴们!今天咱们来聊聊Next.js中那令人又爱又恨的静态生成(Static Generation)和服务端渲染(Server-side Rendering)。这两个概念常常让新手开发者摸不着头脑,甚至有时候连老鸟也会搞混。不过别担心,看完这篇文章,保证你能对这两种渲染方式了如指掌,甚至还能在下次技术分享会上侃侃而谈。

静态生成:build时就把你"拍"下来

首先,让我们来看看静态生成。简单来说,静态生成就是在构建时(build time)就生成HTML页面。这就像是给你的网页拍了一张"全家福",然后把这张照片挂在网上,谁来看都是这一张。

听起来很简单,对吧?但是等等,这里面还有点小花样。

静态生成的两种方式

  1. 无数据依赖的静态生成

    这种方式就像是你穿着平常的衣服拍照。不需要特殊准备,直接就能生成HTML。

    function About() {
      return <div>关于我们</div>
    }
    
    export default About
    

    这个页面在构建时就会生成一个静态的HTML文件。简单粗暴,效率拉满!

  2. 有数据依赖的静态生成

    这种方式就像是你要穿上特定的衣服,化好妆,然后才能拍照。需要先准备好数据,然后才能生成HTML。

    function Blog({ posts }) {
      return (
        <ul>
          {posts.map((post) => (
            <li key={post.id}>{post.title}</li>
          ))}
        </ul>
      )
    }
    
    export async function getStaticProps() {
      const res = await fetch('https://api.example.com/posts')
      const posts = await res.json()
    
      return {
        props: {
          posts,
        },
      }
    }
    
    export default Blog
    

    在这个例子中,getStaticProps函数会在构建时获取数据,然后Next.js使用这些数据来渲染页面。

静态生成的优缺点

优点:

  • 超快的加载速度(因为页面已经准备好了)
  • 可以直接部署到CDN
  • 降低服务器负载

缺点:

  • 内容更新需要重新构建
  • 不适合频繁变化的数据
  • 大型站点构建时间可能很长

服务端渲染:每次都给你化个新妆

而服务端渲染则是每次请求到来时,服务器都会即时生成HTML页面。这就像是你每次出门都会重新化妆,确保自己状态最佳。

服务端渲染的实现

在Next.js中,你可以使用getServerSideProps函数来实现服务端渲染:

function Page({ data }) {
  return <div>最新数据:{data}</div>
}

export async function getServerSideProps(context) {
  const res = await fetch(`https://api.example.com/data`)
  const data = await res.json()

  return {
    props: { data }, // 将作为props传递给页面组件
  }
}

export default Page

每次有请求访问这个页面时,getServerSideProps函数都会运行,获取最新的数据,然后用这些数据渲染页面。

服务端渲染的优缺点

优点:

  • 始终显示最新数据
  • 适合动态内容
  • 有利于SEO(搜索引擎总能看到最新内容)

缺点:

  • 相对较慢的TTFB(Time To First Byte)
  • 增加服务器负载
  • 缓存策略相对复杂

如何选择?

看到这里,你可能会问:"这两种方式我该选哪个呢?"别急,让我们来个简单的决策树:

  1. 你的页面内容经常变化吗?

    • 是 → 考虑服务端渲染
    • 否 → 继续看第2点
  2. 你的页面需要针对每个用户显示不同的内容吗?

    • 是 → 考虑服务端渲染
    • 否 → 继续看第3点
  3. 你的网站需要极快的首屏加载速度吗?

    • 是 → 考虑静态生成
    • 否 → 你真的不在乎速度吗?再考虑一下
  4. 你的网站有大量页面需要预渲染吗?

    • 是 → 可能需要增量静态生成(ISR)
    • 否 → 静态生成可能是个不错的选择

记住,这不是非黑即白的选择。Next.js的强大之处在于,你可以在同一个应用中混合使用这两种方式。某些页面使用静态生成,某些页面使用服务端渲染,简直不要太灵活!

实战小贴士

  1. 利用getStaticPaths进行动态路由的静态生成

    如果你有动态路由,但又想使用静态生成,getStaticPaths就是你的好帮手:

    export async function getStaticPaths() {
      const res = await fetch('https://api.example.com/posts')
      const posts = await res.json()
    
      const paths = posts.map((post) => ({
        params: { id: post.id },
      }))
    
      return { paths, fallback: false }
    }
    
    export async function getStaticProps({ params }) {
      const res = await fetch(`https://api.example.com/posts/${params.id}`)
      const post = await res.json()
    
      return { props: { post } }
    }
    
  2. 使用SWR进行客户端数据获取

    有时候,你可能想在静态页面上展示一些实时数据。这时候,可以考虑在客户端使用SWR库:

    import useSWR from 'swr'
    
    function Profile() {
      const { data, error } = useSWR('/api/user', fetcher)
    
      if (error) return <div>加载失败...</div>
      if (!data) return <div>加载中...</div>
      return <div>你好,{data.name}!</div>
    }
    
  3. 增量静态再生成(ISR)

    如果你想要静态生成的好处,又不想完全放弃数据的新鲜度,可以尝试ISR:

    export async function getStaticProps() {
      const res = await fetch('https://api.example.com/posts')
      const posts = await res.json()
    
      return {
        props: {
          posts,
        },
        revalidate: 60, // 每60秒重新生成页面
      }
    }
    

结语

好了,到这里,你应该对Next.js的静态生成和服务端渲染有了更深入的理解。记住,没有绝对的好坏之分,关键是要根据你的具体需求来选择合适的渲染策略。

下次如果有人问你"Next.js的静态生成和服务端渲染有什么区别",你就可以自信满满地说:“哦,那不就是build时拍照和每次出门化妆的区别吗?”

好了,今天的课程到此结束。下课!别忘了课后练习:试着在你的Next.js项目中混合使用这两种渲染方式,看看效果如何。加油,相信你一定能成为Next.js渲染大师!

海码面试 小程序

包含最新面试经验分享,面试真题解析,全栈2000+题目库,前后端面试技术手册详解;无论您是校招还是社招面试还是想提升编程能力,都能从容面对~

下课!别忘了课后练习:试着在你的Next.js项目中混合使用这两种渲染方式,看看效果如何。加油,相信你一定能成为Next.js渲染大师!

海码面试 小程序

包含最新面试经验分享,面试真题解析,全栈2000+题目库,前后端面试技术手册详解;无论您是校招还是社招面试还是想提升编程能力,都能从容面对~

[外链图片转存中…(img-gQIGO9tW-1720775442347)]

Next.js 中,你可以在服务端启动时执行一些脚本,可以使用 `server.js` 文件自定义服务器端逻辑。你可以在这个文件中编写任意 Node.js 代码,例如: ```javascript const { createServer } = require('http') const next = require('next') const dev = process.env.NODE_ENV !== 'production' const app = next({ dev }) const handle = app.getRequestHandler() // 自定义服务端逻辑 console.log('服务端启动了') app.prepare().then(() => { createServer((req, res) => { handle(req, res) }).listen(3000, (err) => { if (err) throw err console.log('> Ready on http://localhost:3000') }) }) ``` 在上面的例子中,我们在服务端启动时执行了一句打印输出,这就是一个自定义的服务端脚本。 如果你想要执行更多的服务端脚本,可以在 `createServer` 函数之前执行它们。例如: ```javascript const { createServer } = require('http') const next = require('next') const dev = process.env.NODE_ENV !== 'production' const app = next({ dev }) const handle = app.getRequestHandler() // 自定义服务端逻辑 console.log('执行服务端脚本...') // 执行更多的服务端脚本 require('./my-script.js')() app.prepare().then(() => { createServer((req, res) => { handle(req, res) }).listen(3000, (err) => { if (err) throw err console.log('> Ready on http://localhost:3000') }) }) ``` 在上面的例子中,我们通过 `require('./my-script.js')()` 执行了一个名为 `my-script.js` 的脚本。你可以在这个脚本中编写任意服务端代码。注意,这个脚本文件必须在服务端运行,不能在浏览器端运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值