Next.js 系列 02:客户端渲染与服务端渲染
Published on 29th August 2024
- Next.js 系列 01:为什么使用 Next.js
- Next.js 系列 02:客户端渲染与服务端渲染
- Next.js 系列 03:渲染策略
- Next.js 系列 04:在服务器组件之前
- Next.js 系列 05:什么是服务器组件
- Next.js 系列 06:服务器组件的好处
- Next.js 系列 07:客户端组件的传染性
你现在看到这篇文章的内容,是我重写后的。在此之前我花了一些功夫试图解释什么是客户端渲染,什么又是服务端渲染,以及服务端渲染有哪些优势。
但我发现这不是我想要的。老实说,把这两种渲染模式将明白并且达到通俗易懂的程度,我没有足够的信心。我不希望读到这篇文章的人被我误导,所以假定读者对这两者渲染模式均有所知。
Hydration
当我们的应用使用服务端渲染时,浏览器访问我们的网站,在理想情况下,会先得到一个完整的页面,它的 HTML 与 CSS 均由服务器生成(参考文档:Server React DOM APIs), 它是纯静态的,没有任何交互。
但我们使用 React,目的就是创建动态的具有交互的页面。将初始静态 HTML 转换为交互性 Web 的过程,被称为 hydration(参考文档:hydrateRoot)。
React 核心团队成员 Dan Abramov 的解释相当形象:
Hydration is like watering the “dry” HTML with the “water” of interactivity and event handlers.
陷阱
大部分人都知道,服务器没有 window 对象,在 Next.js 有如下代码:
运行开发服务器,你应该会在终端看到类似输出:
这是最常见的陷进之一。
尝试修复
typeof window === ‘undefined’ 是用来判断服务端和客户端的管用手法之一。
此刻,控制台已不再报错,在刷新页面后,也能正确显示我们存在 localStorage 的值。
不幸的是,打开 Developer Tools,会看到新的错误:
Text content did not match. Server: “0” Client: “1”
Text content does not match server-rendered HTML.
这是服务端渲染的另一个陷阱:Hydration 不匹配。
代码在服务器上生成的标记是:
Hydration 时候是:
最终
我们使用 useEffect 来修复它:
useEffect 只会在客户端执行,巧妙的是,它执行的时候,Hydration 已经完成。
本篇,我与你讲述了服务端渲染的两个陷阱,愿你在写代码的过程中能够想起它们。下一篇,我会介绍 Next.js 的渲染策略。