小言_互联网的博客

谈谈 React 新出的 Server Components

402人阅读  评论(0)

昨天看了 demo,今天翻了翻源码。我们应该从几个维度来“看待” React Server Components:

  • 当前开发遇到了哪些痛点?

  • 这些痛点目前有哪几种解决方案?

  • Server Components 是怎么解决这些痛点的?

  • Server Components 是否比这些解决方案更优秀?

  • Server Components 是某一个或某几个解决方案的升级、颠覆还是互补?

而最常拿来和 Server Components 对比的就是传统的 PHP/ASP 技术和为框架而生的 SSR 技术。React Server Components 这个技术,听起来和 SSR 很像,而代码看起来则和 PHP 很像。很多人认为这是一种倒退,“前端好不容易爬到了山顶,却发现 PHP 已经等待多时”。其实恰恰相反,使用一种“和现有技术类似的”方式来解决某个开发痛点的做法,正是一种先进而优雅的方式。就好比 jsx 和 html 很相似,vue template 和 mustache 很相似,极低的减轻了开发者的学习成本。

虽然表面相似,但是却完全不同。

在 PHP/ASP 时代,页面都是由服务器来渲染。服务器接到请求后,查询数据库然后把数据“塞”到页面里面,最后把生成好的 html 发送给客户端。当用户点击链接后,继续重复上面的步骤。这样用户体验不是很好,每个操作几乎都要刷新页面,服务器处理完之后再返回新的页面。

我们可以概括为:

  • 痛点:用户体验太差(user experience)

  • 原因:页面总是刷新

  • 解决思路:让页面别刷新

  • 方案:使用 ajax

而 Angular/Vue/React 这种单页应用(SPA)则主要是客户端渲染。服务器接到请求后,把 index.html 以及 js/css/img 等发送给浏览器,浏览器负责渲染整个页面。后续用户操作和前面的 php/jquery 一样,通过 ajax 和后端交互。但是和 php 相比,第一次访问时只返回了什么内容都没有的 idnex.html 空页面,没法做 SEO。另一点就是页面需要等到 js/css 和接口都返回之后才能显示出来,首次访问会有白屏。

概括一下:

  • 痛点:首次访问白屏

  • 原因:首次访问只返回了 index.html 页面

  • 解决思路:首次访问时返回渲染完的页面

  • 方案:SSR

SSR 的方式是:首次访问的时候由服务器(通常是 Node.js)来渲染页面,然后把已经渲染好的 html 发送给浏览器。后续的用户操作依然通过 ajax 获取数据,然后在浏览器端渲染组件和页面。

那么能不能让首屏的体验更好呢?

  • 痛点:SSR 首屏还是太慢

  • 原因:服务端渲染是请求的接口太多,导致响应时间太长

  • 解决思路:分块渲染,把已经渲染好的部分尽早的发送到浏览器

  • 方案:bigPipe

我们根据这种思路重新审视一下 React Server Components 解决了什么问题。

在视频的开篇,Dan 就举了一个“鱼与熊掌不可兼得”的例子:

  • Good:用户体验

  • Cheap:可维护性

  • Fast:性能

例子很简单,页面中的三个组件应该如何请求数据?

  • 顶层组件通过 1 个接口 fetch 所有数据,这样请求的时候会变长。用户体验✅ 可维护性❎ 性能❎

  • 顶层组件通过 3 个接口并行 fetch 所有数据:用户体验✅ 可维护性❎ 性能✅

  • 每个组件自行 fetch 数据:用户体验❎ 可维护性✅ 性能✅

面对种种痛点,我们也都有自己的方案。比如:

  • 我们可以通过增加服务器配置来解决,或者优化后端代码来解决。解决思路是让接口响应变快。

  • 使用 graphql 按需查询后端数据。

  • ……

React 团队分析了导致痛点的原因:组件需要反复从服务器请求数据。而 React 团队给出的解决方案是:把组件放到服务器端,这样客户端和服务器端只需要往返一次。和 graphql 的思路很像,但是更加贴近 react 生态,也更加 frontend style。

我截取了视频中的 30 秒,很好的说明了这种理念。

graphql 看似美好,但是落地困难。我使用 Gatsby 开发过几个项目,也做过 React Native 的 Facebook 登录,graphql 是真香。但是我觉得影响 graphql 落地的最大障碍就是 “明明是解决的前端痛点,却非要改造后端”。而把 graphql 做 BFF 来用坑也不少。

而 React Server Components 则完全是按 React 的思维来解决这个问题。甚至可以说是按前端组件化的思维来解决这个问题,这种思想 Vue 也可以实现。

前端发起请求,服务器端组件可以查询 db,可以访问接口 api,…… 而且和 SSR 不同,服务器响应的不是 html,而是一个序列化的“指令”。客户端根据此“指令”集来渲染组件和页面。

(PS:服务器直接返回 html 片段的技术也有了,叫 pjax/turbolinks。我去年和一个团队交流,说他们在做基于 React 组件的 pjax,后来放弃了)


   
  1. M1:{ "id": "./src/SearchField.client.js", "chunks":[ "client5"], "name": ""}
  2. M2:{ "id": "./src/EditButton.client.js", "chunks":[ "client1"], "name": ""}
  3. S3: "react.suspense"
  4. J0:[ "$", "div",null,{ "className": "main", "children":[[ "$", "p",null,{ "className": "col sidebar", "children":[[ "$", "p",null,{ "className": "sidebar-header", "children":[[ "$", "img",null,{ "className": "logo", "src": "logo.svg", "width": "22px", "height": "20px", "alt": "", "role": "presentation"}],[ "$", "strong",null,{ "children": "React Notes"}]]}],[ "$", "p",null,{ "className": "sidebar-menu", "role": "menubar", "children":[[ "$", "@1",null,{}],[ "$", "@2",null,{ "noteId":null, "children": "New"}]]}],[ "$", "nav",null,{ "children":[ "$", "$3",null,{ "fallback":[ "$", "div",null,{ "children":[ "$", "ul",null,{ "className": "notes-list skeleton-container", "children":[[ "$", "li",null,{ "className": "v-stack", "children":[ "$", "div",null,{ "className": "sidebar-note-list-item skeleton", "style":{ "height": "5em"}}]}],[ "$", "li",null,{ "className": "v-stack", "children":[ "$", "div",null,{ "className": "sidebar-note-list-item skeleton", "style":{ "height": "5em"}}]}],[ "$", "li",null,{ "className": "v-stack", "children":[ "$", "div",null,{ "className": "sidebar-note-list-item skeleton", "style":{ "height": "5em"}}]}]]}]}], "children": "@4"}]}]]}],[ "$", "p", "94",{ "className": "col note-viewer", "children":[ "$", "$3",null,{ "fallback":[ "$", "div",null,{ "className": "note skeleton-container", "role": "progressbar", "aria-busy": "true", "children":[[ "$", "div",null,{ "className": "note-header", "children":[[ "$", "div",null,{ "className": "note-title skeleton", "style":{ "height": "3rem", "width": "65%", "marginInline": "12px 1em"}}],[ "$", "div",null,{ "className": "skeleton skeleton--button", "style":{ "width": "8em", "height": "2.5em"}}]]}],[ "$", "div",null,{ "className": "note-preview", "children":[[ "$", "div",null,{ "className": "skeleton v-stack", "style":{ "height": "1.5em"}}],[ "$", "div",null,{ "className": "skeleton v-stack", "style":{ "height": "1.5em"}}],[ "$", "div",null,{ "className": "skeleton v-stack", "style":{ "height": "1.5em"}}],[ "$", "div",null,{ "className": "skeleton v-stack", "style":{ "height": "1.5em"}}],[ "$", "div",null,{ "className": "skeleton v-stack", "style":{ "height": "1.5em"}}]]}]]}], "children": "@5"}]}]]}]
  5. M6:{ "id": "./src/SidebarNote.client.js", "chunks":[ "client6"], "name": ""}
  6. J4:[ "$", "ul",null,{ "className": "notes-list", "children":[[ "$", "li", "94",{ "children":[ "$", "@6",null,{ "id": 94, "title": "Untitled feng", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "feng test"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitled feng"}],[ "$", "small",null,{ "children": "6:21 AM"}]]}]}]}],[ "$", "li", "93",{ "children":[ "$", "@6",null,{ "id": 93, "title": "Untitled", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "Null"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitled"}],[ "$", "small",null,{ "children": "6:06 AM"}]]}]}]}],[ "$", "li", "92",{ "children":[ "$", "@6",null,{ "id": 92, "title": "TEST", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "DDD"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "TEST"}],[ "$", "small",null,{ "children": "6:06 AM"}]]}]}]}],[ "$", "li", "90",{ "children":[ "$", "@6",null,{ "id": 90, "title": "测试测试", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "测试测试测试测试测试测试测试测试测试测试测试测试测试测试"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "测试测试"}],[ "$", "small",null,{ "children": "5:49 AM"}]]}]}]}],[ "$", "li", "89",{ "children":[ "$", "@6",null,{ "id": 89, "title": "喵喵喵🐱", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children":[ "$", "i",null,{ "children": "(No content)"}]}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "喵喵喵🐱"}],[ "$", "small",null,{ "children": "5:43 AM"}]]}]}]}],[ "$", "li", "88",{ "children":[ "$", "@6",null,{ "id": 88, "title": "Untitled", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "????"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitled"}],[ "$", "small",null,{ "children": "5:32 AM"}]]}]}]}],[ "$", "li", "87",{ "children":[ "$", "@6",null,{ "id": 87, "title": "test03", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "hahah hahah ahahha"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "test03"}],[ "$", "small",null,{ "children": "5:32 AM"}]]}]}]}],[ "$", "li", "86",{ "children":[ "$", "@6",null,{ "id": 86, "title": "求不要更新了, 老子学不动了", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children":[ "$", "i",null,{ "children": "(No content)"}]}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "求不要更新了, 老子学不动了"}],[ "$", "small",null,{ "children": "5:30 AM"}]]}]}]}],[ "$", "li", "84",{ "children":[ "$", "@6",null,{ "id": 84, "title": "Untitled", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "</math><img src onerror=alert(1)> 1 2 3 4 5 <form> <math><mtext> </form><form> <mglyph> <style></math><img src onerror=alert(1)>"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitled"}],[ "$", "small",null,{ "children": "3:24 AM"}]]}]}]}],[ "$", "li", "83",{ "children":[ "$", "@6",null,{ "id": 83, "title": "Hi,I am Lilei", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "console.log(process)"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Hi,I am Lilei"}],[ "$", "small",null,{ "children": "5:07 AM"}]]}]}]}],[ "$", "li", "81",{ "children":[ "$", "@6",null,{ "id": 81, "title": "到此一游", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "123123123123"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "到此一游"}],[ "$", "small",null,{ "children": "3:23 AM"}]]}]}]}],[ "$", "li", "80",{ "children":[ "$", "@6",null,{ "id": 80, "title": "Untitled", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "asdasdad"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitled"}],[ "$", "small",null,{ "children": "2:32 AM"}]]}]}]}],[ "$", "li", "78",{ "children":[ "$", "@6",null,{ "id": 78, "title": "alert(123)", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "alert(123)"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "alert(123)"}],[ "$", "small",null,{ "children": "2:30 AM"}]]}]}]}],[ "$", "li", "77",{ "children":[ "$", "@6",null,{ "id": 77, "title": "; DROP TABLE *; --", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "; DROP TABLE *; --"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "; DROP TABLE *; --"}],[ "$", "small",null,{ "children": "2:30 AM"}]]}]}]}],[ "$", "li", "76",{ "children":[ "$", "@6",null,{ "id": 76, "title": "Untitled", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "STRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS TESTSTRESS..."}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitled"}],[ "$", "small",null,{ "children": "2:23 AM"}]]}]}]}],[ "$", "li", "75",{ "children":[ "$", "@6",null,{ "id": 75, "title": "🐂🍺", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "🐂🍺"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "🐂🍺"}],[ "$", "small",null,{ "children": "2:15 AM"}]]}]}]}],[ "$", "li", "74",{ "children":[ "$", "@6",null,{ "id": 74, "title": "1111", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "1111"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "1111"}],[ "$", "small",null,{ "children": "2:07 AM"}]]}]}]}],[ "$", "li", "73",{ "children":[ "$", "@6",null,{ "id": 73, "title": "我真帅", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children":[ "$", "i",null,{ "children": "(No content)"}]}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "我真帅"}],[ "$", "small",null,{ "children": "1:59 AM"}]]}]}]}],[ "$", "li", "72",{ "children":[ "$", "@6",null,{ "id": 72, "title": "😲这还可以当讨论区吗", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "太顶了?? 可以的吧 不可以"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "😲这还可以当讨论区吗"}],[ "$", "small",null,{ "children": "5:46 AM"}]]}]}]}],[ "$", "li", "71",{ "children":[ "$", "@6",null,{ "id": 71, "title": "Untitled111", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children":[ "$", "i",null,{ "children": "(No content)"}]}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitled111"}],[ "$", "small",null,{ "children": "1:59 AM"}]]}]}]}],[ "$", "li", "70",{ "children":[ "$", "@6",null,{ "id": 70, "title": "111", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "1111111"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "111"}],[ "$", "small",null,{ "children": "1:49 AM"}]]}]}]}],[ "$", "li", "69",{ "children":[ "$", "@6",null,{ "id": 69, "title": "Cheap, Good, Fast~ It's the best", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "yes"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Cheap, Good, Fast~ It's the best"}],[ "$", "small",null,{ "children": "2:07 AM"}]]}]}]}],[ "$", "li", "68",{ "children":[ "$", "@6",null,{ "id": 68, "title": "There is no silver bullet", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "没有银弹"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "There is no silver bullet"}],[ "$", "small",null,{ "children": "4:22 AM"}]]}]}]}],[ "$", "li", "66",{ "children":[ "$", "@6",null,{ "id": 66, "title": "Dan Abramov is the 🐐gfasdfasdfasdf", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "👍asdfasdfasdfasdfasdfasdfasdf那段时低年级"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Dan Abramov is the 🐐gfasdfasdfasdf"}],[ "$", "small",null,{ "children": "1:58 AM"}]]}]}]}],[ "$", "li", "65",{ "children":[ "$", "@6",null,{ "id": 65, "title": "ss", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children":[ "$", "i",null,{ "children": "(No content)"}]}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "ss"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "64",{ "children":[ "$", "@6",null,{ "id": 64, "title": "Untitledsx", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "这个是一个默认页面"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitledsx"}],[ "$", "small",null,{ "children": "12:09 midnight"}]]}]}]}],[ "$", "li", "62",{ "children":[ "$", "@6",null,{ "id": 62, "title": "This is", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "#Surprisingly Slow"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "This is"}],[ "$", "small",null,{ "children": "4:20 AM"}]]}]}]}],[ "$", "li", "61",{ "children":[ "$", "@6",null,{ "id": 61, "title": "Yekshimesh", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "my name a borat!"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Yekshimesh"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "60",{ "children":[ "$", "@6",null,{ "id": 60, "title": "Elon Musk", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "https://twitter.com/elonmusk is the best"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Elon Musk"}],[ "$", "small",null,{ "children": "2:00 AM"}]]}]}]}],[ "$", "li", "59",{ "children":[ "$", "@6",null,{ "id": 59, "title": ":-)", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": ":)"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": ":-)"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "57",{ "children":[ "$", "@6",null,{ "id": 57, "title": "Readme", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "React Server Components Demo What is this? When will I be able to use this? Setup DB Setup Step 1...."}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Readme"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "56",{ "children":[ "$", "@6",null,{ "id": 56, "title": "HGV great", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children":[ "$", "i",null,{ "children": "(No content)"}]}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "HGV great"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "55",{ "children":[ "$", "@6",null,{ "id": 55, "title": "HGV just tesing!", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "Hello, world!"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "HGV just tesing!"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "54",{ "children":[ "$", "@6",null,{ "id": 54, "title": "Hello", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "Hello??"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Hello"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "53",{ "children":[ "$", "@6",null,{ "id": 53, "title": "holyshit find another job", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "holyshit find another job"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "holyshit find another job"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "52",{ "children":[ "$", "@6",null,{ "id": 52, "title": "狗子们又要学新东西啦", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "狗子们又要学新东西啦 Really interesting."}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "狗子们又要学新东西啦"}],[ "$", "small",null,{ "children": "1:22 AM"}]]}]}]}],[ "$", "li", "51",{ "children":[ "$", "@6",null,{ "id": 51, "title": "å†…å·å·æ­»ä½ ", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "å†…å·å·æ­»ä½ "}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "å†…å·å·æ­»ä½ "}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "50",{ "children":[ "$", "@6",null,{ "id": 50, "title": "HI", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "测试测试知乎小弟留"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "HI"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "49",{ "children":[ "$", "@6",null,{ "id": 49, "title": "又有新概念啦", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "又有新概念啦"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "又有新概念啦"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "48",{ "children":[ "$", "@6",null,{ "id": 48, "title": "From Vietnam", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "theuranuskjkj #fdfdf dfdsf dfdsfds 地方就乐山大佛 对方水电费"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "From Vietnam"}],[ "$", "small",null,{ "children": "3:49 AM"}]]}]}]}],[ "$", "li", "47",{ "children":[ "$", "@6",null,{ "id": 47, "title": "; DROP TABLE *; --", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "'); DROP TABLE *; --"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "; DROP TABLE *; --"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "46",{ "children":[ "$", "@6",null,{ "id": 46, "title": "Hello React Server Compoenents", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children":[ "$", "i",null,{ "children": "(No content)"}]}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Hello React Server Compoenents"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "44",{ "children":[ "$", "@6",null,{ "id": 44, "title": "Why there are no loading indicators?", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "If I click on some notes, it freezes for a bit and only then transitions to the needed page. But..."}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Why there are no loading indicators?"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "42",{ "children":[ "$", "@6",null,{ "id": 42, "title": "Untitledasd", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children":[ "$", "i",null,{ "children": "(No content)"}]}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitledasd"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "41",{ "children":[ "$", "@6",null,{ "id": 41, "title": "Youtube", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "Oh no! What have I done? FR Rechercher Image d'avatar 55:56 / 57:19 Data Fetching with React Server Components 17..."}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Youtube"}],[ "$", "small",null,{ "children": "2:49 AM"}]]}]}]}],[ "$", "li", "39",{ "children":[ "$", "@6",null,{ "id": 39, "title": "Dupa", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "z trupa hmmm this is nice"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Dupa"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "38",{ "children":[ "$", "@6",null,{ "id": 38, "title": "Untitledd", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "dddd"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitledd"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "37",{ "children":[ "$", "@6",null,{ "id": 37, "title": "New Note", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "it's a bit slow?"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "New Note"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "35",{ "children":[ "$", "@6",null,{ "id": 35, "title": "Untitled", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "Hello"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "Untitled"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "34",{ "children":[ "$", "@6",null,{ "id": 34, "title": "q121Untitled", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "sadasdasd"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "q121Untitled"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "2",{ "children":[ "$", "@6",null,{ "id": 2, "title": "test", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children": "India"}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "test"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}],[ "$", "li", "1",{ "children":[ "$", "@6",null,{ "id": 1, "title": "测试下", "expandedChildren":[ "$", "p",null,{ "className": "sidebar-note-excerpt", "children":[ "$", "i",null,{ "children": "(No content)"}]}], "children":[ "$", "header",null,{ "className": "sidebar-note-header", "children":[[ "$", "strong",null,{ "children": "测试下"}],[ "$", "small",null,{ "children": "12/22/20"}]]}]}]}]]}]
  7. J5:[ "$", "div",null,{ "className": "note", "children":[[ "$", "div",null,{ "className": "note-header", "children":[[ "$", "h1",null,{ "className": "note-title", "children": "Untitled feng"}],[ "$", "div",null,{ "className": "note-menu", "role": "menubar", "children":[[ "$", "small",null,{ "className": "note-updated-at", "role": "status", "children":[ "Last updated on ", "23 Dec 2020 at 6:21 AM"]}],[ "$", "@2",null,{ "noteId": 94, "children": "Edit"}]]}]]}],[ "$", "div",null,{ "className": "note-preview", "children":[ "$", "div",null,{ "className": "text-with-markdown", "dangerouslySetInnerHTML":{ "__html": "<p>feng test</p>\n"}}]}]]}]

所以本质上还是客户端渲染。视频中小姐姐还演示了一个例子:点击左侧内容时组件使用到了过渡效果,就如同普通的 React 程序一样,完全不受服务器端组件的影响。

Server Components 的这种思路还有很大的挖掘空间。比如可以开发 WebSocket Components,通过 WebSocket 向浏览器主动的实时推送“指令”。再比如可以开发 Native Components,在 App 内嵌的 H5 页面中向原生代码发请求,原生代码完成业务处理后返回给 H5 序列化的“指令”。

这种序列化的指令还可以被存储,可以被回放,可以被 mock,调试起来应该可以像 redux 一样具有时间旅行功能。

总之,对 Server Components 还是挺期待的。


转载:https://blog.csdn.net/justjavac/article/details/111601818
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场