Qwik 与 React Hydration 有何不同

本文对比了Qwik和React在处理客户端JavaScript方面的差异,特别是Qwik的Resumability技术,它通过精细的分块和按需加载显著减少了性能浪费。作者通过酒吧和啤酒的类比生动解释了两者的工作原理和优势。
摘要由CSDN通过智能技术生成

本文译者为 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(反馈)组件。

就像下面这样:

1941963b111c560865a1088aa7e12895.jpeg

这个组件负责这些工作:

  • 做一个客户端 GET 请求,获取用户可以针对本贴所有的反馈信息。

  • 点击这些反馈按钮,会做一个客户端 POST 请求提交反馈。

Qwik 的处理策略非常智能。

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

6dbf4370b0f724018ba1199bd8970c8c.jpeg

到目前为止,仅有差不多 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 的过程中非常享受,并且我经常惊讶于不需要考虑太多,就能获得如此出色的性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值