Qwik 与 React Hydration 有何不同

本文译者为 360 奇舞团前端开发工程师 

原文标题:JavaScript on Demand: How Qwik Differs From React Hydration

原文作者:Paul Scanlon

原文地址:https://thenewstack.io/javascript-on-demand-how-qwik-differs-from-react-hydration/

在本文中,我将深入介绍 Resumability (可恢复性),这一 Qwik 用来解决繁杂的客户端 JavaScript 问题的技术。我还将说明这和 React 的处理方式有何不同。

QwikSchool.com 上有一个很棒的 Qwik 视频入门课程,教程会涵盖我在本文中讲的一些东西。但对我来说,阅读是更适合我的学习方式,使用类比的方式学习,我就能学的更快。所以,我会在本文中用「酒吧」和「啤酒」来做些类比,让你更好理解。

React Hydration 是如何工作的

想象一下,你走进一间酒吧坐下,但酒保没有让你点单,而是直接拿了个大杯子,倒进去 6 品脱(品脱 pint 是英式和美式体系中常用的体积单位)啤酒。当酒保确认杯子确实能装 6 品脱酒后,他就会把酒全倒掉。然后,酒保会递给你(客户端)一个空杯子,再给你倒上 6 品脱酒。

你最终需要为这 12 品脱的酒付钱,而其中 6 品脱是被倒掉的,也就是说其中一半其实是你当时不需要的。

React Hydration 就是这么工作的。

Qwik Resumability 是如何工作的

想象一下,你走进一间酒吧坐下,酒保会让你点单。你说:”请给我一品脱啤酒“。酒保接着会将一品脱啤酒倒入一个正常大小的杯子,并递给你。

你将为这一品脱酒付钱。简而言之这就是 Qwik Resumability。

从顶层去看,你会发现,相比于 Qwik,React 的处理方式存在着巨大的性能浪费,且没有一个非常精准的方法来确定什么时候需要进行处理,需要处理多少。

重现 React Hydration

我们继续使用前文提到的例子,酒保把 6 品脱啤酒倒入一个大杯子,然后全倒掉,最后递给你(客户端)一个空杯子,再重新倒酒。

React 在服务器上进行渲染时,就会发生这样的事。应用程序在服务端构建,之后被丢弃。服务器会把 HTML 发送到客户端,随后发送一大段 JavaScript 代码,这些代码是用于在客户端(浏览器)上重现服务端渲染的过程。如果在重现过程中发生什么异常,导致失败,你会在控制台看到 Hydration 的相关错误信息。

服务器需要构建一次页面,如此它才能知道自己要向客户端发送什么东西,这就解释了 React Hydration 重现 过程中的一半。但也许你会问,为什么在我啤酒的比喻里,6 品脱是一次倒出来的?答案就是「路由分块」。

什么是「路由分块」?

不同版本的 React 框架可能会略微有些不同,但总的来说「路由分块」是在描述这样一种技术:服务器在对 React 应用进行构建时,框架会基于用户正在查看的页面路由,找出所需的 JavaScript。例如,如果用户正在访问 /dashboard 路由,那他需要的 JavaScript 和访问 /settings 路由的用户是不同的。页面路由会决定哪些 JavaScript 应该被包含在分块里。这技术真是太智能了,不过我们还能做的更好。

什么是「动态组件分块」(Dynamic Component Chunking)?

Qwik 的处理方式颗粒度更细。它不使用基于用户正在访问路由来决定要包含哪些 JavaScript 的方法,它把 JavaScript 分成小的多的多的小块。这些更小的块可以被更加快的发送到客户端。不仅如此,Qwik 能够查明用户正在访问给定路由的行为,并以此提供这些更小的 JavaScript 块。

我需要 $

在 Qwik 库中,不管是什么都带着 $ 后缀。比如,下面这个简单的组件,我们用 component$() 把他包起来了。

import { component$, $ } from '@builder.io/qwik';
 
const SimpleQwikComponent = component$(() => {
    
  const handleClick = $(() => {
    console.log('Hello world!');
  });
 
  return (
    <div>
      <p>Hello, I'm a simple Qwik component</p>
      <button onClick$={handleClick}>Click me</button>
    </div>

  );
});
 
export default SimpleQwikComponent;

多亏了 $ 语法,Qwik 能容易的对分块边界进行优化,这样一来就能构建出更小的独立 JavaScript 分块。

另外,这也有助于在根据需要时提供这些小 JavaScript 块。

以 onClick$ 为例。这段代码实际上仅在用户点击按钮时是需要的。如果用户没有点击按钮,这段在控制台输出 Hello world! 的 JavaScript 将仅存在于浏览器缓存(已由 Qwik 的 service worker 拉取),它不会被优先下载,而是会等到实际需要的时候在下载。

换一个例子,想想看,如果有一个大型应用程序,它有着很多不同的交互区域,你是否觉得:「所有用户在任何时候都需要全量的 JavaScript」?也许,一些用户某些时候只是需要其中一部分 JavaScript,你觉得呢?

Service Worker

事情变得有趣起来了。你可能听说过 Partytown,这是 Qwik 的创建者做的一个开源库,它能帮你把一些客户端脚本(比如 Google Analytics)加载转移到 service worker 上。通过将不必要的脚本转移到 service worker 上,我们解放了浏览器主线程,我们的应用程序可以更有效率的载入自己的代码,让应用程序表现的更出色。

不过...

默认情况下,Qwik 利用 service worker 来载入你的应用程序代码!那么说不定,从另一个角度看,这意味着你可以继续在主线程载入 Google Analytics,但这么做对性能的影响应该也很有限。🤷

一旦通过 service worker 载入 JavaScript,JavaScript 就会被浏览器缓存,所以下次用户访问时可能会重用已经下载的代码,Qwik 会从这些缓存中载入,而不是从网络。现在我的啤酒类比法不太好说明这个问题,但... 希望你能理解这些点。

正式的例子

举个例子,在我的站点上,每一个「帖子」页面都有一个 Reactions(反馈)组件。

就像下面这样:

这个组件负责这些工作:

  • 做一个客户端 GET 请求,获取用户可以针对本贴所有的反馈信息。
  • 点击这些反馈按钮,会做一个客户端 POST 请求提交反馈。

Qwik 的处理策略非常智能。

让我说说 Qwik 厉害在哪里。下面是我那篇帖子的 network 选项卡截图:

到目前为止,仅有差不多 19kb 的 JavaScript 在页面上载入了(这是 Qwik 的核心代码)。

我们向下滚动一些,当 Reactions 组件进入视口,Qwik 会载入所需的独立 JavaScript 分块,即用来展示那些笑脸的分块,并启动一个客户端 GET 请求来获取。

不过等等,还没结束哦。

和 Reactions 组件进行交互(这会导致发送一个 POST 请求)后,你会发现 Qwik 又一次载入了所需的 JavaScript 分块,用于让按钮点击逻辑生效。

这些分块非常小,在我这个例子中,大部分尺寸都小于 1kb!

Qwik 的思路

这就是 Qwik 的思路。只在所需的时间,载入所需的 JavaScript。对于像 Reactions 这样的组件来说,这一点尤为重要。Reactions 组件位于一个基本上可以被视为「静态页面」的页面底部。这意味着该页面不需要从服务器端拉取数据或进行服务器端渲染,因此其加载速度会比需要服务器端渲染(SSR)的页面更快。然而,尽管 Reactions 组件位于这样的静态页面中,它仍然需要执行 GET 和 POST 请求。

大部分时候,我帖子的读者不会滚动到页面最下方,因此他们确实不需要页面那部分的任何数据,不需要载入那部分的 JavaScript。不过,如果读者要向下滚动,Qwik 会介入并智能的选择「何时载入」、「载入什么」。太有才了!

React 的思路

当然,可能用 React 也能达成类似的效果吧。你可以自己整一个 intersection observer,并把它和 React 的 lazy / suspense 技术结合起来,这样数据(以及交互所需的 JavaScript)获取仅会在组件滚动到视口的时候进行,不过呢,这些东西都需要你作为一个开发者去考虑和优化,Qwik 可是替你把这些东西都考虑过了!

最后的想法

虽然酒吧和啤酒的类比可能看起来有点奇怪,但我相信在实际应用中,这个理论是站得住的:「你/用户」只应该在 需要的时候 点那些 你需要的 并 为之付钱

老实说,应用程序代码之间有什么不同呢?无端地抛弃一半,不经询问的过度交付、过度收费,这真的没什么道理。讲真,我们只希望简简单单为那些我们点的东西付钱。

Qwik 团队撰写了一份技术说明文档,你应该去读一读:Resumable vs. Hydration。如果你想对 Qwik 感兴趣,那你应该了解一下!我在学习 Qwik 的过程中非常享受,并且我经常惊讶于不需要考虑太多,就能获得如此出色的性能。


相关推荐

  • 卢伟冰称小米汽车定价“有点贵”;蚂蚁集团启动组织升级;​微软聘请 DeepMind 联合创始人 | 极客头条
  • Java 22 来了!
  • OceanBase独立运营后首次亮相,谈了两件事
  • 7万字:2023腾讯云容器和函数计算最佳实践精选集上线,等你翻「阅」!
  • 40 张图搞懂分布式日志追踪,强大的traceId
  • 今日代码 PK | 使用 Optional 判空
  • 永久激活 GPT4.0 !无限使用!即将结束!
  • 全职开源四年,一切并没有那么简单。
  • Spring Boot集成Debezium快速入门demo
  • 博士申请 | 香港大学陈怡老师课题组招收计算机安全方向全奖博士/博后
  • CVPR 2024 | 通过细粒度人类反馈对齐数据,提高多模态大模型可信度
  • TPAMI 2024 | 针对节点的融合全局-局部信息的图谱滤波方法
  • 多领域文献阅读超越GPT-4!深势科技发布科学文献多模态大模型Uni-SMART技术报告
  • 警惕发布前夕的“致命遗忘”
  • 邀你探索金融、教育、法律及医疗行业的大模型创新应用,AICon 2024 即将拉开帷幕
  • Java 22 正式发布
  • 微软开抢年收入上亿美元的 Redis 饭碗?开源性能遥遥领先的 Garnet:无需修改,Redis 客户端可直接接入
  • 风控也在用大模型了
  • 一次性支持 200 万字无损上下文!Kimi智能助手玩了个大的——月之暗面「登月」最新进展!
  • 今日arXiv最热NLP大模型论文:大模型RAG新宠!浙江大学发布自反馈检索增强方法