React
7️⃣React SSR
00 分钟
2024-5-17
2024-8-1

一、认识SSR

(一)提出问题

问题的提出——单页面富应用的局限
之前我们开发的应用程序,如果直接请求可以看到上面几乎没有什么内容。但是为什么我们页面可以看到大量的内容呢?因为当我们请求下来静态资源之后会执行JS,JS会去请求数据,并且渲染我们想要看到的。
这个过程存在另外两个问题:问题一:首屏显示的速度较慢;问题二:不利于SEO的优化;
直接请求单页面富应用的html页面
直接请求单页面富应用的html页面
问题解决:采用服务端渲染

(二)SSR与同构

*️⃣ SSR与CSR
SSR,即Server Side Rendering,服务端渲染,指的是页面在服务器端已经生成了完成的HTML页面结构,不需要浏览器解析。与之对应的是CSR(Client Side Rendering,客户端渲染),我们开发的SPA页面通常依赖的就是客户端渲染。
早期的服务端渲染包括PHP、JSP、ASP等方式,但是在目前前后端分离的开发模式下,前端开发人员不太可能再去学习PHP、JSP等技术来开发网页,不过我们可以借助于Node来帮助我们执行JavaScript代码,提前完成页面的渲染。
*️⃣ 同构
一套代码既可以在服务端运行又可以在客户端运行,这就是同构应用。同构是一种SSR的形态,是现代SSR的一种表现形式。当用户发出请求时,先在服务器通过SSR渲染出首页的内容,但是对应的代码同样可以在客户端被执行。执行的目的包括事件绑定等以及其他页面切换时也可以在客户端被渲染

(三)Next.js 脚手架

使用React SSR主要有两种方式:
  • 方式一:手动搭建一个SSR框架;
  • 方式二:使用已经成熟的SSR框架:Next.js ✅
安装Next.js框架的脚手架:npm install create-next-app -g
创建Next.js项目:create-next-app next-demo,然后选择需要用到的配置,E.g. Ts、Eslient,最后通过 npm run dev 在本地运行项目。
💡
安装选择配置信息有一项「√ Would you like to use src/ directory? ... No / Yes」,如果选择Yes,项目主要代码结构是src/app;否则是app作为根目录。
该步骤也会影响自动路由页面配置,假如项目主要代码结构是src/app,那么需要将页面放置在「src/pages」里面才能触发页面路由。E.g. 通过localhost:3000/about访问src/pages/about界面。

二、Next.js

(一)参考资料

(二)路由与跳转

1. 页面跳转×SSR or CSR

在原生的html中我们通常使用 <a> 进行页面跳转,如以下案例代码
我们可以从控制台看到此时仍然是SSR渲染
notion image
 
假设我们需要CSR渲染呢?我们可以参考以下代码:
然后我们查看控制台,发现请求的是js文件而不是html文档
notion image

2. <Layout>×_app.ts

公共布局组件 <Layout>
部分组件如Header和Footer,对于大部分页面都是存在的,只是他们中间渲染的东西不一样,此时我们需要用到 <Layout> 组件。在 Next.js 中,布局(Layouts)是一个 UI 组件,它在应用程序的多个页面之间共享。布局允许我们为一组页面定义通用的结构和外观,减少冗余并促进代码可重用性。
以下是 <Layout> 组件的例子:
首先我们写一个公共的 <Sidebar> 组件
 
以下是 Layout 组件的核心环节,在此处引入sidebar使其成为公共组件
再加入CSS样式美化页面
具体效果
具体效果
 
剩下就是如何调用我们的Layout组件,以下代码通过 Index.getLayout 设置需要使用 <Layout> 包裹的页面。
但是假设我们一些页面不需要用到 <Sidebar> 组件,我们可以通过以下代码进行设置
 
思考为什么可以通过 Index.getLayout 控制是否显示 <Sidebar>
这是上一层控制代码:
 
💡 总结:如果需要设置公共组件,可以首先将代码设置在一个 <Layout> 组件中,其次通过给需要调用公共代码的页面设置一个layout函数(16行)。
 

3. 页面跳转与数据传递

假设我们需要页面跳转的携带参数并且传给下一个页面,我们可以通过query的方式进行传递参数,以下是案例demo,通过两种方式实现需求。
1️⃣ href属性的url拼接
这个是发送数据的页面:
以下是接受数据的页面:
 
2️⃣ 通过事件进行跳转

(三)页面显示配置

1. <Head>

<Head> 组件可以用于设置标题和logo,具体代码如下
其他next接口也可以参见以下官方文档

2. _document.js

该文件应该放置于「./pages/_document.js」,该文件通常用于增强应用程序的 <html><body> 标签,因为 Next.js 页面忽略了周围文档标记的定义。

(四)添加样式

1. 全局变量

通常全局的样式存放在globals.css文件中,并在「pages/_app.tsx」中进行引入,在项目运行打包的时候,全局的CSS就会被成功加载。

2. 局部变量

*️⃣ CSS Modules技术实现
以Index页面为例,我们首先编写CSS文件,⚠️ 需要注意的是,文件名必须要以 .module.css 结尾才能使局部变量生效不会影响其他视图组件。
然后在视图页面进行引入并调用
 
*️⃣ styled-jsx
styled-jsx是Css in js的技术的一种,该模块在Next.js中已经集成,具体代码如下
 
*️⃣ styled-components
需要注意Next.js本身并没有支持styled-components,所以需要我们先手动安装依赖:yarn add styled-components
编写组件样式:
在组件中使用样式:
在sidebar中添加一个 <Link> 组件指向「/profile」
但是我们发现一个问题,假设从主页点击Profile菜单进入页面,页面的样式生效;但是假设我们直接通过「http://localhost:3000/profile」访问样式不生效且出现报错:「Warning: Prop className did not match. Server: "sc-fqkwJk cDZRcr" Client: "sc-aYaIB bpURGb"」
原因是通过 <Link> 组件跳转时是客户端渲染,但是直接通过url访问是服务器渲染,但是默认情况下服务器并不会按照预期匹配classNames,此时我们需要依赖一个开发时的插件「babel-plugin-styled-components」来解决服务端渲染问题。安装:yarn add -D babel-plugin-styled-components
然后需要修改部分文件的代,首先需要在项目根目录下创建文件「.babelrc」
修改「pages/_document.tsx」

(五)fetch数据

假设我们需要在加载页面时获取一些数据并挂载到视图上,Next.js在这部分中与React的编码方式有一些不同。
以下介绍三个相关的函数 getInitialPropsgetStaticPropsgetServerSideProps
 
1️⃣ getInitialProps()
该函数在页面会启用服务端渲染并允许进行初始数据填充,这意味着请求到的页面时已从服务器填充的数据,其有利于SEO。⚠️ 需要注意,启用该函数将禁用自动静态优化,意味着每次请求页面时都需要执行一次 getInitialProps,因此 Next.js 无法在构建时静态生成页面,只能在每次请求时动态生成。
补充:静态优化优点
  1. 更快的页面加载:静态生成的页面可以直接从 CDN 获取,减少服务器负载,提升页面加载速度。
  1. 更好的 SEO:静态页面对搜索引擎更加友好,因为它们可以被预渲染并且内容是完全可见的。
  1. 降低服务器负载:静态页面不需要每次请求都访问服务器生成内容,这样可以减少服务器的压力。
以下是该函数的使用方法:
由于 getInitialProps 的存在,每次请求这个页面时,都会调用 getInitialProps 获取数据并动态生成页面。
但是,在 Next.js 的最新版本中,官方建议使用 getStaticPropsgetServerSideProps 来代替 getInitialProps,这是因为这两个函数具有更好的性能和灵活性:
  • 性能优化
    • getStaticProps 允许在构建时生成静态页面,极大地提升了页面的加载速度和性能。
    • getServerSideProps 允许在每次请求时生成页面,确保数据是最新的,同时可以利用服务器端的能力优化渲染。
  • 更好的开发体验
    • getStaticPropsgetServerSideProps 提供了更明确的生命周期方法,便于开发者理解和使用。
    • 这些方法的类型签名和数据流更符合现代 React 开发的模式。
  • 自动静态优化
    • 如果页面使用 getStaticProps 并且所有的数据都是在构建时就已经确定的,Next.js 会自动优化这些页面为静态页面,不需要额外配置。
 
2️⃣ getStaticProps()
该方法主要用于在构建时预渲染页面,这对于内容不经常变化的页面非常有用,比如博客文章、产品页面等。
优点:
  • 性能高:生成静态页面,页面加载速度非常快。
  • CDN 友好:静态页面可以很容易地分发到全球的 CDN 中,进一步提升访问速度。
  • SEO 友好:静态页面对搜索引擎更加友好,有助于 SEO。
 
3️⃣ getServerSideProps()
该方法用于在每次请求时生成页面,这对于数据变化频繁的页面非常有用,比如用户仪表盘、动态列表等。
优点:
  • 数据总是最新的:每次请求都会重新生成页面,确保数据是最新的。
  • 服务器端处理:可以利用服务器端的资源和能力,处理复杂的数据逻辑。
 
💡
getStaticProps()getServerSideProps() 的使用时机问题
*️⃣ 对于 getStaticProps()
  • 内容相对静态的页面
    • 例如博客文章、产品展示页、文档页面等,这些页面的内容在发布后很少更改。
    • 由于内容在构建时生成,页面的加载速度非常快。
  • 构建时获取数据
    • 如果你的数据源在构建时可以访问(例如从数据库、CMS 或外部 API 获取数据),并且这些数据不需要频繁更新。
  • 提升性能和 SEO
    • 静态生成的页面可以被缓存和部署到 CDN,显著提升性能。
    • 对于需要优化 SEO 的页面,静态生成的页面对搜索引擎更加友好。
  • 增量静态再生成(ISR)
    • 即使数据偶尔会更新,也可以使用 ISR。在 ISR 模式下,页面在构建时生成,并在特定时间间隔后重新生成,确保页面在用户访问时是最新的。
*️⃣ 对于 getServerSideProps()
  • 内容动态变化的页面
    • 例如用户仪表盘、购物车、订单详情页等,这些页面的数据在每次请求时都可能不同。
  • 需要实时数据的页面
    • 当页面必须展示最新的数据,例如股票行情、新闻网站、社交媒体动态等。
  • 基于请求的个性化内容
    • 需要根据用户请求中的参数(如查询字符串、Cookies、身份验证令牌等)动态生成页面内容。
  • 服务器端处理复杂逻辑
    • 在服务器端处理一些复杂的数据逻辑或 API 调用,然后将数据传递给客户端渲染。
 
 
notion image

 
上一篇
仿网易云 Demo
下一篇
Vue3入门

评论
Loading...