type
status
date
slug
summary
tags
category
icon
password

1. 前言

此为《Next.js 14 App Router 海底捞针我帮你做了!》的下篇,主要讲解在 Next.js 中的网络数据请求,对路由有疑惑的可看上篇。

2. 路由中间件

在传统的后端框架(Express.js、Koa.js)中,我们可以使用中间件对进入站点的请求进行一些处理,比如身份认证、重定向、日志分析等业务逻辑。
鉴权的方案可以参考笔者的另一篇文章——Next.js 14 踩坑:处理API中的JWT登录认证问题

3. Fetch API 与数据请求

数据请求是每一个应用都具备的非常关键的功能之一。下面是在不同类型组件中请求数据的方式。

3.1 服务端组件

默认情况下,组件就是服务端组件,得到请求后会在服务端渲染成 HTML,然后给到客户端,然而这些页面不可能永远是静态的,服务器数据是会更新的。
  1. 使用 fetch
在 Next.js 中,原生的 fetch 得到了扩展,在请求服务端请求数据时,它允许你配置数据缓存(cache)和重新验证时间(revalidate),从而更新最新的页面显示。
下面是一个在服务端组件中使用 fetch 的例子:
在不同的服务端组件中重复请求相同的数据并不会产生什么性能损耗,这是因为 Next.js 加入了自动记忆功能,这对性能优化来说是一种极大的提升,减少了大量的数据获取。
需要说明的是,在上篇中提到的 cookies、headers 也都可以在这里的请求中去使用,不过这些动态函数会使请求失去缓存性质。
通过设置 revalidate 可以修改缓存数据的时效性:
  • 基于时间的重新验证
    1. 使用第三方库
    有的第三方库,例如:数据库、CMS 或是 ORM 客户端,它们并不支持 fetch,cache 和 revalidate 的设置就没有办法直接在 fetch 上配置了。
    在 Next.js 中允许通过 React 的 cache 函数或 Route Segment Config Option 来配置,下面是一个示例:
    • 用 cache 函数缓存数据请求
    • revalidate 配置为 3600s,这意味着数据将会每隔 1 小时才更新一次
    注意:数据是否被缓存取决于路由段(route segment)被静态或动态渲染。默认情况下,路由段是静态的,请求的结果将会被缓存。反之,如果是动态渲染(比如使用了动态函数 cookies、header 等),那么结果不会被缓存,每次渲染,都会重新请求。

    3.2 客户端组件

    当想要使用use相关的hook或想要添加点击等交互事件时,组件顶部要加上"use client" ,使之成为客户端组件。
    1. 通过路由处理器(Route Handler)
    上篇提到的路由处理器在服务端运行,然后返回数据给客户端。当不想暴露 token 等敏感数据时,就可以用它来请求数据。
    注意:在服务端组件直接使用 fetch 获取数据即可,如上节。
    1. 使用第三方库
    同样可以利用 SWR 来请求数据,就像直接编写 React 那样。

    4. 渲染策略 SSR、SSG、ISR 的请求方式

    上面的客户端组件本质上是 CSR,另外在 App Router 中,SSR、SSG、ISR 也换了马甲,差点不认识了。

    4.1 SSR(Server-side Rendering,服务端渲染

    服务端请求接口、获取数据,渲染成 HTML 返回给前端。
    在 Page Router 中使用 async getServerSideProps 实现 SSR,而 App Router 中是这样的:
    通过配置 { cache: 'no-store' } 退出缓存,这样每次调用时会重新获取数据。

    4.2 SSG(Static Site Generation,静态站点生成

    构建阶段就将页面编译为静态的 HTML 文件,配合 CDN 缓存直接起飞。
    在 Page Router 中的 SSG:
    • 不请求数据时就是 SSG,但很多还是需要请求数据的
    • 页面内容需要获取数据(单个的静态页面生成)——async getStaticProps
    • 页面路径需要获取数据(成组的静态页面生成)——async getStaticPaths
    而 App Router 中是这样的:
    { cache: 'force-store' } 是 fetch 中默认的缓存方式,每次请求时将从缓存中读取数据。(如果使用了动态函数,则会变为 no-store,因此不必担心数据被静态化)

    4.3 ISR(Incremental Static Regeneration,递增式静态再生

    在一个主体内容不变的博客页面中,点赞、评论等功能则是动态变化的,这种场景下就可以用 ISR。
    在 Page Router 中使用 async getStaticProps + revalidate 实现 ISR,可以理解为定时更新的静态页面。
    而 App Router 中是这样的:
    通过设置 { next: { revalidate: 10 } } 使之定时更新,从而实现 ISR。

    5. Meta 元数据

    动态设置网页标题并且为了更好的 SEO。

    5.1 静态元数据

    5.2 动态元数据

    6. <Image> 组件

    假设 blog.src 不是本站的图片,则需要在 next.config.js 中添加外部图片地址:

    7. 总结

    总之,组件被分为服务端组件和客户端组件,辅以数据缓存和验证,当然不是说缓存越多越好,有些需要根据查询参数动态获取的内容当然不能固执地去使用缓存。
    作为开发全栈应用的React框架,Next.js 一直在不断优化和提高中,体验感还是很好的。除了本文提到的内容,Next.js 还有一些大家可以自由探索,比如:Server Actions、身份认证、国际化等。
    非要说瑕疵,可能就是文档比较复杂,没有中文文档,笔者根据路由和数据请求两条线挖掘文档,才有这些内容,如果掌握了这些去开发一个应用完全没问题。
     
    听说你还不会 Tailwind CSS(基础·上篇)Next.js 14 App Router 海底捞针我帮你做了!(上)
    Eric 见嘉
    Eric 见嘉
    Less is more.
    公告
    type
    status
    date
    slug
    summary
    tags
    category
    icon
    password
    💭
    合抱之木,生于毫末;九层之台,起于累土;千里之行,始于足下。

    关于我
    土木转行的前端开发工程师,陆续分享技术干货。
    联系我
    微信公众号:见嘉 Being Dev