这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
课程笔记
基础知识
我们可以将Web应用分为B端和C端两种
-
B端
设计的功能和产品主要是在内网(或本地网络)使用,不能够为外网用户提供服务。
-
C端
能够被外网用户访问使用的功能产品和服务。
Next.js适用于开发C端应用而不是用于开发B端应用的框架。
-
首屏时间
用户从向地址栏输入地址到页面元素展示出来的时间称为
首屏时间
-
SPA
单页面应用
,它所需的资源(HTMLCSSJS等),在一次请求中就加载完成,不需刷新地动态加载,首屏时间更长(因为要一次性加载所有东西)。 -
BFF
Backend For Frontend,服务于前端应用的后端。
可以理解为是前端与后端之间的一个中介。
使用BFF可以提升项目的可维护性和可复用性。 -
CDN
建立并覆盖在Internet之上,由分布在不同区域的边缘节点服务器群组成的分布式网络。
-
同构
服务端与客户端都要进行相同的页面构造才能将页面实现。
-
脱水与注水
在服务器端返回html的过程中,将其中的初始化数据脱出来变成水,即下例中展示的代码的部分,然后在客户端渲染的时候,拿出服务端在浏览器端注入的水,放入这个页面中,从而保证客户端和服务器端保持一致。
-
CSS Modules
Next.js支持使用文件命名约定的CSS模块([name].module.css)。
前端主流渲染方式
前端的主流渲染模式分为CSR、SSR和SSG三种。
-
CSR
客户端渲染(Client-Side Rendering)。常见B端WEB应用开发模式,前后端分离,服务器压力相对更 轻,渲染工作在客户端进行,服务器直接返回不加工的HTML,用户在后续进行访问操作。
在这种渲染模式下首屏时间是会更长的。
由上图可以看到服务器端返回的只有简单的HTML。
-
SSR
服务器端渲染(Server-Side Rendering),原先的JSP/PHP就已经体现了服务器端渲染。
代码耦合度高,且模板语言中混杂编程语言,对于一些复杂的功能维护起来很棘手。
这种模式下Java或PHP负责渲染的逻辑,而前端只负责UI和交互。
现如今这种开发模式已经很少采用了。
由上图可以看出后端代码和UI代码耦合度很高,不好应用于大型项目且不易于维护。
-
同构SSR
简单来说就是服务器端返回到客户端的是一套完整的页面。前后端一体化,一套React代码在服务器上运行一遍,到达浏览器又运行一遍。前端后端都要参与渲染,而且首次渲染出的HTML要一样。
如上图所示,后端的API接口和前端的页面代码都在同一个项目目录下,这就与之前的SSR不同。
常见的同构SSR渲染模式的流程如下图
从图中也看出同构SSR模式需要前端与后端都参与渲染。
-
SSG
静态站点生成(Static Site Generation),在构建的时候直接把结果页面输出html到磁盘,每次访问直接把html返回给客户端,相当于一个静态资源。
相比SSR,因为不需要每次请求都由服务器端处理,所以可以大幅减轻服务器端的压力。 缺陷在于只能用于偏静态的页面,无法生成与用户相关的内容,也就是所有的用户访问的页面都是相同的。
SSR和SSG的优势
SSR和SSG的主要优势在于
-
利于SEO
浏览器的推广程度,取决于搜索引擎对站点检索的排名,搜索引擎可以理解是一种爬虫,它会爬取指定页面的HTML,并根据用户输入的关键词对页面内容进行排序检索,最后形成我们看到的结果。
-
更短的首屏时间
SSR/SSG只需要请求一个HTML文件就能展现出页面,虽然在服务器上会调取接口,但服务器之间的通信要远比客户端快,甚至是同一台服务器上的本地接口调取。因为不再需要请求大量js文件,这就使得SSR/SSG可以拥有更短的首屏时。
Next.js
什么是Next.js
基于React提供的相关服务器端渲染API实现,整个过程实现比较繁琐重复,从零实现对新上手同学很不友好,所以我们迫切需要个封装好的集合来快速上手服务器端渲染。
Next.js框架的定位就是帮助我们更好更快地开发一个SSR/SSG项目。
Next.js是一个构建于Node.js之上的开源Web开发框架,支持基于React的Web应用程序功能,例如服务端渲染和生成静态网站。
上手快,能力集全,而且覆盖了足够多的性能优化和生态。
对于新同学掌握前后端一体化的开发模式很友好。
Next.js客户端开发
Next.js初始化
将项目demo从仓库clone到自己的电脑上
使用命令npx create-next-app@latest --typescript
进行初始化。
目录结构简单说明:
-
next-env.d.ts
确保TypeScript编译器选择Next.js类型,可以放到.gitignore中,不需要变更
-
next.config
nextjs的配置,我们可以补充webpack的一些配置进行
数据注入
Next.js客户端最重要的部分就是数据注入,这也是和平常开发React项目最不同的地方。
Next.js提供了三种数据注入方式,分别为getServerSideProps
、getStaticProps
、getInitialProps
三个API。
-
getInitialProps
一个比较老的API,在服务器端执行,只能在页面层面进行绑定,采用同构,首次渲染服务器端渲染,路由跳转使用客户端路由。意味着如果使用router跳转当前页,会在客户端执行这部分逻辑。
-
getServerSideProps
SSR,与getlnitialProps不同的是即使使用router跳转当前页,也只会在服务端执行这部分逻辑。
-
getStaticProps
SSG,在服务器端构建时执行如果涉及动态路由(带参数)需要使用getStaticPaths配置所有可能的参数情况。
Layout
当我们需要制作一些类似于官网的页面的时候,我们要进行页面的布局,在Next.js中我们可以定义一个Layout组件来实现。
文件式路由
在Next.js中是没有router这样一个文件的,因为Next.js并不是通过一个文件来进行路由匹配的。
Next.js有一个基于页面概念的基于文件系统的路由器。当一个文件被添加到pages目录中时(除了api文件),它会自动作为一个可用路径。
预定义路由优先级更高,预定义路由能直接匹配的路由就不会分发给下面的动态路由
BFF层的文件式路由
在项目的pages目录下有个api文件目录,这个api就是我们前面所说的BFF。
BFF,作为服务器构建包,不影响客户端构建bundle体积。相同的router生成方式,不过是作为API层访问,而不是page。
路由跳转
Next.js中路由跳转有两种方式
-
next/link跳转
使用Link组件,将跳转的链接放入组件的href中即可实现路由跳转。
-
useRouter跳转
在useRouter钩子里直接调用router.push来进行路由跳转。
除了这些外,还可以使用原生方法(window.open等)跳转,不过原生的方法不会进行Diff比对渲染,性能上Next.js提供的路由跳转会更好。
header修改
页面的header内容是会影响到SEO效率的,所以header修改也是重要的一部分。
在C端开发中,header部分最重要的三个点为title
、description
和keywords
(简称为TDK)。例如掘金官网首页的TDK如下
在Next.js中我们可以使用其提供的Head
组件来进行TDK的修改。
多媒体适配
我们所做的页面通常都需要在不同的终端设备(手机、平板)上浏览,所以为了在每种终端上都能有很好的展示效果我们需要进行多媒体适配。
CSS适配
通常,我们对于需要进行多媒体适配的页面在编写时会使用rem
来作为样式的计算单位,这种方式也称为CSS适配。
如上图中的对四种设备的适配方案包含了绝大多数的多媒体场景。
JS适配
但有时页面上的交互功能很多且复杂,这时候使用CSS适配就达不到我们想要的预期效果了甚至会导致页面排布混乱。
此时我们就需要使用JS适配来使页面在不同的终端上保持良好的交互效果。在Next.js中我们主要使用UserAgentProvider
注入器来实现JS适配,具体的demo代码如下
将写好的注入器填到useContext
中,我们就可以取到注入器返回的内容。
大图优化
当我们的页面中有一个很大的图片时(例如几百kb),在慢网速的环境下访问页面则会出现页面加载完毕但图片还在加载中的情况。为了解决这种问题,我们可以将图片格式转换为webp格式,这样图片的体积会小很多很多。
但webp并不是所有设备都兼容的,所以我们需要先检查设备浏览器是否支持webp格式,可以在浏览器开发者页面中的Request Headers中查看是否有imge/webp
,有则代表支持否则不支持webp。
此时我们就需要在页面中使用一个方法来判断当前的浏览器支不支持webp格式,若不支持webp格式我们就需要使用PNG格式作为默认的格式以防止图片加载不出来。
类似的检测webp的通用方法如下
(这里有一个很有意思的东西,webp在慢网速情况下可以相比之前快速的加载图片,但是在极快网速下webp的加载甚至会比同环境下原来图片加载的时间还长一些。这是因为webp虽然体积很小,但是它需要更长的解析时间,慢网速情况下图片原加载时间远比webp解析时间长,所以会有明显提升,而极快网速下,图片原加载时间远比webp解析时间短很多,这就导致了这种现象的产生。)
Next.js服务端开发
Next.js服务器端开发的部分和Express等开发类似,区别是并没有参数可以直接区别请求类型。(Next.js生成的路由不区分GET和POST等方法)
调试方式
-
在VSCode中使用JavaScript Debug Terminal来进行调试
在这个控制台下我们可以调试服务器端的代码,在终端正常运行dev命令即可。然后按照Node.js的方式来进行断点调试即可。
- 使用命令
npm run debugger
进行调试
执行该命令后切换到浏览器客户端,点击绿色按钮则可以使用浏览器进行调试。
Strapi - headless CMS
CMS:数据管理平台,即这个平台维护着页面的所有数据,当我们需要修改数据内容时不必重新编写页面内容,而是直接通过数据管理平台修改相应的数据即可。(数据管理平台相较于数据库更加适合运营的同学来使用和维护数据)
我们可以使用Strapi来快速帮我们搭建一个CMS平台。其仓库地址:htps://github.com/strapi/strapi
在CMS项目demo中我们通过命令npx create- strapi- app my - project -- quickstart
来对项目进行初始化。
一个接口的生成有以下几个过程:
- content- type builder 编辑结构体。(数据源和结构体是一一对应的关系)
- content manager 配置数据源,并且发布。
- settingsroles里选择对应角色并勾选要发布的接口类型。
- 如果涉及嵌套,在接口后加上populate=deep参数。
(
npm install strapi- plugin-populate-deep --save
),没安装加参数populate=*,但只能嵌套一层。
总结
通过本次课程,大致对Next.js有了一定的了解,从Next.js客户端到Next.js服务端的介绍,自己对使用Next.js开发SSR页面有了大致的了解。刚入门Next.js还有很多不明白和不理解的地方,自己还需多加实践才能对这个技术有更好的理解。