SSR
目前市面上的C端网站大都全部已经向ssr看齐了,所以想要打造一个快速seo和fcp的web应用。ssr是作为我们前端人员必不可少的技能。ssr主要是以node环境返回的html页面,以实现运行的过程在服务端,这样就没必要把运行阶段的时间消耗在客服端了。
import express from "express";
import childProcess from "child_process";
import { renderToString } from "react-dom/server";
import Home from "@/pages/Home";
const app = express();
const content = renderToString(<Home />);
app.get("*", (req, res) => {
res.send(`
<html
<body>
<div>${content}</div>
</body>
</html>
`);
});
app.listen(3000, () => {
console.log("ssr-server listen on 3000");
});
childProcess.exec("start http://127.0.0.1:3000");
为什么要学习next?
市面上也出现了许多框架如nuxt和next分别是vue和react的服务端渲染的方案。为什么我要选择next而不是nuxt呢,主要目前为止不管是官方的重视程度还是社区的活跃度,在目前的市场环境里nuxt的成熟度还不如next。所以本次的分享主要是以next来学习ssr的解决方案。
什么是NextJs
首先查看NextJs官网给出了如下的解释(官网地址: nextjs.org):
The React Framework for the Web. Used by some of the world's largest companies, Next.js enables you to create
high-quality web applicationswith the power of React components
总结就是用的公司多,框架水平NB,经住了很多项目的磨练。然后官网就给出了NextJs学习教程,做一个Dashboard网站。
个人觉得官网的解释还不是很有说服力,于是找了一些比较好的文章。
总结就是服务端渲染+完善的工程化机制
Next.js 可以带给我们什么?
Next.js 是一个 React web 应用框架,这是官方对自己的定义,然后它主要做的事情有以下几点:
- 完善的工程化机制
- 良好的开发和构建性能
- 智能文件路由系统
- 多种渲染模式来保证页面性能体验
- Suspense与Streaming
完善的工程化机制
你不需要自己去配置 webpack 方案,它已经内置了以下工程化基础:
babel内置,支持JS代码向后兼容postcss内置,支持CSS代码向后兼容browserslist支持配置兼容的浏览器信息,配合babel和postcss工作。TypeScript可选择使用,保证代码的质量,以及可阅读性和可维护性。eslint可选择使用,检测代码格式,可自定义规则。vscode 编写代码,或者build打包时都会有提示。prettier可通过扩展使用,格式化代码,可自定义规则。css modules内置css-in-js可扩展使用tailwind css可扩展使用
多种渲染模式来保证页面性能体验
渲染模式是决定页面性能很重要的因素,也是 Next.js 最核心的一部分,如next可以帮助我们随时在组件里开启不同的渲染模式。
Next.js 实现 CSR
以下都以app route为例子
// pages/csr.js
"use client"
import React, { useState, useEffect } from 'react'
export default function Page() {
const [data, setData] = useState(null)
useEffect(() => {
const fetchData = async () => {
const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`)
}
const result = await response.json()
setData(result)
}
fetchData().catch((e) => {
console.error('An error occurred while fetching the data: ', e)
})
}, [])
return <p>{data ? `Your data: ${JSON.stringify(data)}` : 'Loading...'}</p>
}
Next.js 实现 SSR
export default async function Page() {
const data = await getData()
return (
<>
<h1>图片 ID:{data[0].id}</h1>
<img src={data[0].url} width="300" />
<CatDetail />
</>
)
}
Suspense与Streaming
1、Suspense
传统ssr的缺点,传统的ssr渲染是线性的、阻塞的,传统ssr的渲染步骤如下:
- 服务端获取所有数据
- 服务端渲染 HTML
- 将页面的 HTML、CSS、JavaScript 发送到客户端
- 使用 HTML 和 CSS 生成不可交互的用户界面(non-interactive UI)
- React 对用户界面进行水合(hydrate),使其可交互(interactive UI)
这意味着服务端只能在获取所有数据后渲染 HTML,React 只能在下载了所有组件代码后才能进行水合
为了解决这些问题,React 18 引入了 组件。我们来介绍下这个组件:
<Suspense> 允许你推迟渲染某些内容,直到满足某些条件(例如数据加载完毕)
你可以将动态组件包装在 Suspense 中,然后向其传递一个 fallback UI,以便在动态组件加载时显示。如果数据请求缓慢,使用 Suspense 流式渲染该组件,不会影响页面其他部分的渲染,更不会阻塞整个页面。
// app/dashborard/page.js
import { Suspense } from 'react'
const sleep = ms => new Promise(r => setTimeout(r, ms));
async function PostFeed() {
await sleep(2000)
return <h1>Hello PostFeed</h1>
}
async function Weather() {
await sleep(8000)
return <h1>Hello Weather</h1>
}
async function Recommend() {
await sleep(5000)
return <h1>Hello Recommend</h1>
}
export default function Dashboard() {
return (
<section style={{padding: '20px'}}>
<Suspense fallback={<p>Loading PostFeed Component</p>}>
<PostFeed />
</Suspense>
<Suspense fallback={<p>Loading Weather Component</p>}>
<Weather />
</Suspense>
<Suspense fallback={<p>Loading Recommend Component</p>}>
<Recommend />
</Suspense>
</section>
)
}
Streaming
介绍
Suspense 背后的这种技术称之为 Streaming。将页面的 HTML 拆分成多个 chunks,然后逐步将这些块从服务端发送到客户端。
智能文件路由系统
next智能化的配置了一系列的文件的路有导航系统,我们可以先从next的目录结构看起: