RSC是什么
RSC 是 React Server Components,React 通过文件名后缀将组件分为Server Component(.server.jsx)和Client Component(.client.jsx),Server Component将会在服务端进行渲染并且返回给客户端。以解决WaterFall
的数据请求队列问题。
什么是Nextjs
Nextjs是一个React的上层框架,可以让你通过React来创建高质量的Web应用程序。
Nextjs有什么优点,相较于create-react-app
作为React的上层框架,Nextjs:
1.内置了路由处理程序,可以不再需要自己配置React-router。
2.提供了SSR的解决方案,同时也可以使用静态页面构建你的Web应用。或者使用最新的RSC方案。
3.可以选择你喜欢的CSS工具,包括模块化、Tailwind CSS等。
4.由于Nextjs提供了SSR解决方案,所以其本质是一个Node服务器,可以轻松的构建后端服务以及中间件和路由处理程序等。
现在开始Nextjs吧
1.初始化一个项目
Terminal
npx create-next-app@latest
需要Node.js 18.17或者更高版本
Terminal
What is your project named? my-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias (@/*)? No / Yes
What import alias would you like configured? @/*
其中的App Router
是Nextjs的新功能,使用App Router
可以允许你使用React的新功能,也就是本文的主题,server component
同时,Nextjs的路由是约定式的,Next会根据你的项目的文件结构来生成一套路由映射。
/app/page.jsx 会被映射为根路径,也就是 /
同理,/app/user/page.jsx 会被映射为 /user
初始化完成之后的项目目录结构为:
2.RSC的一些注意事项
使用RSC
一定要注意区分server component
和 client component
从上图就可以看出,server component
主要负责数据的获取以及对一些私密数据的保护;而client component
更注重于交互以及使用浏览器api 和React Hooks。
注意:
server component
不能注册事件和使用React Hooks, 也不能将函数作为属性传递(这是因为函数是不可序列化的,详细的原因可以搜索一些RSC的原理,React 会在收到服务器传来的序列化React节点信息之后将其与客户端组合,恢复React的结构以及进行水合)
3.自己试试
现在咱们有一个简单的列表页面,数据来源为咱们的数据库。
想一想,换成以前会怎么做?
在 React 的
useEffect
Hooks中进行数据请求,然后通过useState
进行数据更新和页面渲染
如果是SSR呢?
用户实际请求的是服务器,服务器通过进行本地的数据库查询之后,将所得数据注入前端页面模版,然后返回一个HTML页面。
或者是使用Nextjs这类框架,通过getStaticProps这类api进行数据的查询和注入。
但是现在使用RSC:
jsx
'use server'
import { List, ListItem } from '@chakra-ui/react';
import MyButton from '@/components/MyButton';
import { PrismaClient } from '@prisma/client';
const Page = async () => {
// select data from database
const prisma = new PrismaClient();
const userList = await prisma.user.findMany() || [];
return (
<main className="flex flex-col items-center pt-24 h-svh">
<div className="w-1/2 flex flex-col">
<List spacing={3}>
{
userList.map(user => (
<ListItem key={user.id} className="w-full flex flex-col px-2 py-4 rounded-lg border border-my-color shadow-none hover:shadow-my-shadow duration-500">
<div className="text-xl font-medium">{`userId: ${user.id}`}</div>
<div className="text-xl font-medium">{`name: ${user.name}`}</div>
<div className="text-xl font-medium">{`E-mail: ${user.email}`}</div>
</ListItem>
))
}
</List>
<MyButton href="/" type='a'>Back</MyButton>
</div>
</main>
);
};
export default Page;
在Nextjs中,可以使用'use server'
来定义一个server component
, 你可以在这个异步组件或是异步函数中进行任何服务器的操作(或者说是Node的操作,只要你想象力够丰富,内嵌一些其他语言的操作也可以),就像咱们一样,使用prisma进行了数据库内容的查询。
这是页面:
很直观的效果,仔细的朋友可能会注意到我们的这个MyButton
组件:
jsx
'use client'
import NextLink from 'next/link';
const MyButton = ({ href = '/', type = 'button', children, onClick }) => {
const classTag = 'w-max bg-transparent hover:bg-my-color-light text-lg font-medium text-center text-my-color border border-my-color rounded mt-8 py-2 px-4 text-lg duration-500';
return (
type === 'button' ? <button onClick={onClick || null} className={classTag}>{children}</button> : <NextLink href={href} className={classTag}>{children}</NextLink>
);
};
export default MyButton;
这个组件是怎么回事呢,因为我想把我的button和link统一一下,顺便试试client component,所以就随便写了一个这个组件。因为我们在组件中绑定了事件,所以需要用'use client'
将其声明为client component,这使我们可以在这个组件中使用到一些server component无法使用的功能,如事件绑定以及React Hooks等等。
你可以这样来进行用户的数据提交,使用useState绑定数据,通过在事件处理函数中发起请求提交数据。(或者是使用Nextjs的server form,Nextjs对form进行了魔改,使其的action可以接受一个server component作为参数来进行数据的提交处理)
最后
RSC 与 SSR 的区别
1.SSR是在服务器进行HTML拼接然后返回给客户端;而RSC是在客户端渲染的,服务端只是输出了组件的序列化信息
2.SSR的请求响应为HTML,是无状态的;而RSC是有状态的
可以使用SSR进行首屏渲染,其他页面使用RSC
RSC 的优点
1.数据在服务端获取,相比于发送请求来说更快
2.Zero-Bundle-Size:RSC 的最终打包更小,服务器的组件以及依赖不会出现在客户端的打包中,也避免了一些服务器组件所使用额大型库重复下载的情况
3.配合 React 的 Suspense 来获取更好的用户体验