预渲染:静态生成 & 服务端渲染 概念说明 —— NextJS

1,885 阅读4分钟

23.8.24更新:本文仅针对nextjs/pages使用中的静态生成、服务端渲染概念。 nextjs已经有更新的/app使用方式了;通过页面顶部use clent;区分服务端和客户端渲染的内容。

参考

Next.js 官方教程 预渲染:nextjs.org/learn/basic… (文中图解也都使用官方文档中的图片)

预渲染Next.js 的一个重要概念, Next.js 也提供了开箱即用的 预渲染 功能!

阅读本篇文章,你将了解什么是 服务端渲染 ,以及更好的选择 静态生成  

一、预渲染

1.1 预渲染 是什么?

预渲染 指预先生成包含页面结构的 html 文件,这样在下载到 html 文件后,用户即可快速查看页面(此时也可执行如点击 <a> 标签之类的纯 html 操作)。随后 js 的下载完成并执行,则让页面有了更多交互(这一步也被称为Hydration)  

可见预渲染不用等 js 下载完成,再靠客户端执行 js ,来将 dom 添加进 html

预渲染提供了更好的性能、体验,也更有利于SEO(搜索引擎优化;搜索引擎会爬取 html 内容来收集页面内容,当然也因搜索引擎不同而异)

默认情况下, Next.js 会预渲染每一个页面

1.2 检查是否有 预渲染

通过以下2个步骤,可以看到预渲染的作用:

  1. 设置浏览器禁用 JavaScript
  2. 重新获取页面

预渲染的应用,允许我们在不执行 js 的情况下,就能看到页面UI

而无预渲染的应用,禁用 js 后,则无法看到页面

1.3 预渲染 与 无预渲染 对比

预渲染图解:

image.png

无预渲染图解:

image.png

二、预渲染 的2种模式

Next.js 提供的预渲染有2种模式:静态生成服务端渲染

2.1 静态生成(打包时)

在打包时就预生成每个页面的 html 文件。之后 html 文件不会重新生成,用户的每次请求,都可以复用这些 html 文件

image.png

2.2 服务端渲染

每次用户请求时,由服务端预先生成 html 文件

image.png  

Next.js 支持为每个页面选择不同的预渲染方式

2.3 2种模式如何选择?

推荐 静态生成 ,因为 html 只在打包时生成一次,并且之后可由 CDN 提供下载优化

比起对每个请求都生成 html 文件的 服务端渲染 快很多

静态生成 可以用在很多场景:

  • 博客页面
  • 帮助、文档
  • 产品列表
  • 等等

在2种模式之间选择时,应该问自己“我能在用户请求之前预渲染这个页面吗?”。如果是,你应使用 静态生成

如果页面上的数据实时变化,且与用户请求相关。这种情况可以使用服务器渲染 ,这会更慢,但预生成的页面能保持最新。虽然如此,也可以选择 静态生成 ,预渲染不包含实时数据的部分,随后再由 js 来获取数据填充进去

三、 Next.js静态生成

接下来,我们主要介绍一下 Next.js 预渲染的 静态生成 模式

静态生成支持包含数据的模式

3.1 无数据模式 的 静态生成

如果页面在预生成 html 时不需要拉取额外数据,则这些页面在打包时可直接自动生成 html

image.png

3.2 有数据模式 的 静态生成

有时,你希望预生成 html 时, html 中能包含一些从 API、或文件系统 获得的额外数据

Next.js 支持这样的功能:

image.png

Next.js 每个页面都支持 async getStaticProps() 函数

该函数 仅在构建时执行,且不会出现在客户端代码里!

故该函数其实是一个 node 脚本,可以使用 fs 读文件,也可直接使用数据库 sdk 进行查询

函数返回值将作为参数传入组件

官方教程示例中实现的博客网站,就是在getStaticProps() 函数中读取文件系统里的 markdown 文件。将 md 文件列表、内容都传入组件中使用

也因为在 getStaticProps() 中就读取了文件内容(这一步也使用 remark-html 库,将 md 转换为了 html ),所以项目打包时, md 文本内容全都已经包含在静态生成的 html 中了

部署后,访问博客网站,不需要其它请求,仅 html 就可以看到文章内容

至此,对 预渲染静态生成服务端渲染 2种模式 已经有了基本认识