最近React又出了新的特性,react server components
,目前还属于开发期,并不稳定。但是,从React的这些动作可以看出,前端在如何渲染页面的道路上,一直在探索,在改变,也在朝着更快,更优雅,体验更好的方向努力。
- 官网资料:https://reactjs.org/blog/2020/12/21/data-fetching-with-react-server-components.html
- 知乎文章
青铜时代 - PHP/ASP/JSP
这是最早的服务器渲染。服务器接到请求后,查询数据库然后把数据“塞”到页面里面,最后把生成好的 html 发送给客户端。当用户点击某个链接后,继续重复上面的步骤,展示新的页面。
这个时期,有各种各样的后端模板出现,最常见的应该是jsp。前后端未分离,每个程序员基本是全栈开发,纯前端岗位很少。
代码可能是这样的:
image.png
代码语言:javascript复制<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<form action="beandemo.jsp" method="post">
用户名:<input type="text" name="username">
密码:<input type="password" name="password">
<input type="submit" value="Submit">
</form>
</body>
</html>
痛点
用户体验自然比较糟糕,每个操作几乎都要刷新页面,服务器处理完之后再返回新的页面。 而且,前端技术发展被后端牢牢制约住,举步维艰。
白银时代 - SPA
Ajax兴起之后,程序终于可以将JavaScript从HTML页面里分离出来(感谢谷歌),利用Ajax动态获取云端数据的能力,从而实现HTML的动态渲染。
这一时期,出现了很多优秀的SPA框架,Top 3 的自然为Angular/Vue/React三驾马车。Angular提供了整套解决方案,而React和Vue更专注在View层。
单页应用(SPA)主要为客户端渲染。服务器接到请求后,把 index.html 以及 js/css/img 等发送给浏览器,浏览器负责渲染整个页面。后续用户操作和前面的 php/jquery 一样,通过 ajax 和后端交互。
SPA一个典型的特征是,服务器返回的HTML body体,除了一个根DOM节点再无其他内容。
HTML可能是这样的:
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="description" content="React with Server Components demo">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="style.css" />
<title>React Notes</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
所以,痛点也就显而易见了。
痛点
- 第一次访问时只返回了什么内容都没有的 index.html 空页面,没法做 SEO。
- 页面需要等到 js/css 和接口都返回之后才能显示出来,首次访问会有白屏。
PS:后期我们通过骨架屏方式可以缓解白屏的糟糕体验。
黄金时代 - SSR
为了解决SEO和首屏优化,且基于Node.js大行其道,前端开辟了SSR新的渲染方式。
第一次访问时由服务器(通常是 Node.js)来渲染页面,然后把已经渲染好的 html 发送给浏览器。后续的用户操作依然通过 ajax 获取数据,然后在浏览器端渲染组件和页面。
这种模式看起来很像早期的JSP(核心思想都是服务端完成页面渲染工作),最大的不同在于,其建立在前端成熟的生态模式上,是基于Node.js同构方案的最佳实践。React有next.js框架,Vue有nuxt.js框架,都可以同样的组件开发方式支持客户端和服务端不同渲染。
以next.js为例,关键的入口文件_app.js
可能是这样的:
import React from 'react'
class MyApp extends App<any> {
static async getInitialProps(options) {
const { ctx } = options
const {
req,
query: { code },
} = ctx
...
return { pageProps, }
}
render() {
return (
<Container>
<Head>
<title>
{title || __.common.title}-{__.common.title_suffix}
</title>
<meta name="description" content={description || __.common.meta_description_default} />
<meta name="keywords" content={keywords || __.common.meta_keywords} />
</Head>
<Provider store={reduxStore}>
<Layout>{HocComponent}</Layout>
</Provider>
</Container>
)
}
}
痛点
SSR 首屏还是太慢。 原因:服务端渲染时请求接口太多,导致响应时间太长。
新时代的尝试:react server components
用官网视频里面的两张图来对比下react server components和普通的react components区别。
现在的模式是,客户端从服务端获取数据,然后基于数据渲染组件。
image.png
react server components模式,直接在服务端获取组件。
image.png
官网给了Demo 例子:https://github.com/reactjs/server-components-demo,有人将其部署,在线体验:https://react-server-components.musicfe.dev/
我们跟着Demo,看下整个流程是怎样的。
1. 启动本地服务器
image.png
2. webpack打包
image.png
从ReactServerWebpackPlugin
插件配置可以看出,server components
是不会被打包到build包里面的。
3. 页面初始化
image.png
没有.client.js
或.server.js
后缀的js文件,既可以作为服务端组件使用,也可作为客户端组件使用。
4. 首屏渲染
image.png
首屏根据location
对象(会序列化为缓存KEY)从缓存中获取server组件,通过response.readRoot()
取到组件对象,渲染组件。
5. Cache.client
createFromFetch
如何响应呢?
6. server端处理
server-handler.png
看一眼../build/react-client-manifest.json
的本地mock数据是怎样的:
{
"file:///Users/yelan/git-study/server-components-demo/src/Cache.client.js": {
"": {
"id": "./src/Cache.client.js",
"chunks": [
"main"
],
"name": ""
},
"*": {
"id": "./src/Cache.client.js",
"chunks": [
"main"
],
"name": "*"
},
"useRefresh": {
"id": "./src/Cache.client.js",
"chunks": [
"main"
],
"name": "useRefresh"
},
"useServerResponse": {
"id": "./src/Cache.client.js",
"chunks": [
"main"
],
"name": "useServerResponse"
}
},
...
}
schema的含义,笔者还不明,等待更官网的解释吧。
7. 浏览器请求情况
Request:
request.png
Response:
reponse.png
如此一来,大致的流程就比较清晰了。
那么,Server Components和SSR的区别在哪里呢?
- SSR是在服务端把js转成HTML,返回给客户端(基于不同SSR框架,客户端会视情况重新做全量或者部分重复渲染);而Server Components在服务端输出chunks,客户端渲染组件。
Server Components和SPA的区别呢?
- 如果组件依赖云端数据,那么,SPA是在客户端同时做数据获取和组件创建,而Server Components下客户端获取到的组件已经是经过数据处理过的纯组件。
Server Components目前有什么局限性呢?
- 不能使用
state
、effects
、以及浏览器的一些API,目前只适合用在纯展示的组件。比如商品列表等。