干货 | 新时代的 SSR 框架破局者:qwik

理解vue ssr原理并自己搭建简单的ssr框架 主要介绍了理解vue ssr原理并自己搭建简单的ssr框架,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 立即下载

作者简介

19组清风,携程资深前端开发工程师,负责商旅前端公共基础平台建设,关注NodeJs、研发效能领域。

引言

今天这篇文章中和大家聊一聊号称世界上第一个 O(1) 的 JavaScript SSR 框架:qwik。

别担心,如果你不是特别了解 SSR 也没关系,文章大概会从以下几个方面作为切入点:

  • 首先会围绕对比 SSR 与 SPA 各自的优劣势,从而展开 SSR 的运行机制以及 SSR 相较于 SPA 究竟为了解决什么问题。

  • 之后,会根据 NextJs 的运行机制思考针对目前主流 SSR 框架设计思路上存在的不足从而引出 qwik 为何会在众多成熟框架中脱颖而出。

  • 最后,会针对于 qwik 提出自己的看法以及聊聊目前 qwik 存在的“问题”。

诸如社区内部 SSR 框架其实已经产生了非常优秀的作品,比如大名鼎鼎的 NextJS 以及新兴势力代表的 Remix 和 isLands 架构的 Astro、Fresh 等等优秀框架。

为何 qwik 可以在众多老牌优秀框架中脱颖而出。接下来,让我们一起来一探究竟吧。

一、SSR & CSR

目前业内存在非常多基于 SSR 的优秀框架,比如 Next、Remix、Nuxt 等等。

针对于 Qwik 我们先来聊聊基于 Next 体系的传统 SSR 方案。

1.1 Client Side Rendering

在开始 SSR 之前我们先来聊聊它的对立面,所谓的 CSR(Client Side Rendering)。

服务器端渲染 (SSR) 是一种在服务器中进行渲染 HTML 而不是由浏览器中执行 JS 获得网页(SPA)的技术。

目前国内社区中主流框架比如 VueJs、React 等严格意义上来说都是基于 CSR(Client Side Rendering) 的产物。

所谓 CSR 的意味着当发出一个请求时,服务器会返回一个空的 HTML 页面以及对应的 JavaScript 脚本。

比如:

<html>
<head> 
   <title>携程商旅</title> 
</head> 
 
<body> 
     <div id="root"> </div> 
     <script src="./index.js"> </script> 
 </body>
 </html>

当浏览器下载完成对应的 JS 脚本后才会动态执行对应的 JS 脚本然后在返回的 HTML 页面上进行渲染页面内容。

你可以简单的理解为上述的 ./index.js 会在客户端下载完成后执行该脚本,从而执行 document.getElementById('root').innerHTML = '...' 来进行页面渲染。

这种方式并不是从服务端下发的 HTML 文件来进行渲染页面,相反而是通过浏览器获取到服务端下发 HTML 中的所有的 JS 文件后执行 JS 代码从而在客户端通过脚本进行页面渲染。

以及通常在 CSR 中当我们点击任何页面中的导航链接并不会向服务端发起请求,而是通过下载的 JS 脚本中的路由模块(比如 ReactRouter、VueRouter 这样的模块)重新执行 JS 来处理页面跳转从而进行页面重新渲染。

上面的概念是非常典型的 CSR ,浏览器仅仅接受一个用作网页容器的 HTML 页面,这样的方式通常也被称为单页面应用 (SPA)。

1)优势

那么上述我们提到的 CSR 广泛存在于目前大量页面中,必然存在它自己的优势。

在页面初始化访问后加载速度极快且响应非常迅速。在页面初始化后,网站所有的 HTML 内容都是在客户端通过执行 JS 生成,并不需要再次请求服务器即可重新渲染 HTML 。

此外,有关任何实时的数据获取都可以通过 AJAX 请求对于页面进行局部更新从而刷新页面。

2)劣势

可是,CSR 真的有那么完美吗。任何一件技术方案一定存在它的两面性,我们来看看 CSR 方式究竟存在哪些问题:

  • 初始加载时间长。

首次请求完服务器获取到 HTML 页面后,初始化的页面仍然需要在一段时间内处于白屏状态。

在初始渲染之前,浏览器必须等待 HTML 页面中的所有 Javascript 脚本加载完成并且执行完毕,此时页面才会进行真正的渲染。

当然,使用代码拆分或延迟加载等多种方案可以有效的减少上述的问题。但是这些方式始终是治标不治本,因为它并没有从本质上解决 CSR 存在的问题。

  • SEO(搜索引擎优化) 的负面影响。

上边我们提到过,所谓 CSR 本质上首先会返回一个空的 HTML 页面,所以这也就造成了在搜索引擎对于该页面的数据爬取中会认为它是一个空页面。从而影响对应的搜索结果排名。

虽然说在最新的 Google 中已经可以触发执行 JS 对于网站进行关键字排名,但是在 JS 体积足够大的时候针对于 SEO 仍然是存在一部分问题导致无法解析出正确的关键字匹配。

当然 CSR 还存在一些其他方面的缺点,比如网站强依赖于 JS 当用户禁用 JS 时网站只能是白屏展现给用户等等之类。

1.2 Server Side Render

简单聊完客户端渲染后,我们稍微来看看所谓的服务端渲染是什么含义。

基于旧时代的类似 Java 的 JSP 页面我在这里就不赘述了,显然 JSP 的方式每个 HTML 都需要单独请求服务器返回对应的 HTML 内容严格意义上来说这也是 SSR 的方式但是很明显这已经被时代淘汰了。

目前国内各家公司广泛应用的服务端渲染技术大概的思路是这样的(Next 的 SSR 模式也是同样的思路):

当用户首次访问你的应用站点时:

  • 首先服务器会根据对应的 URL 在服务端根据对应路径渲染对应的 HTML 模版。

    注意这里渲染的 HTML 模版是具有该页面真正的内容。同时它并不具备任何交互逻辑(比如 DOM 元素的点击事件),这是一份完全的静态站点。

  • 服务器会下发这份仅具有静态内容的 HTML 模版,同时这份模版中也会包含对应的 JavaScript 执行脚本。

    第一时间会展示给用户对应的 HTML 页面,此时对于访问站点的用户来说首屏渲染相较于 SPA 应用来说会非常快。因为它并不需要在客户端浏览器上再次下载和执行 JavaScript 脚本来进行页面渲染。

    其次,针对于 SEO 的优化也会非常良好,因为服务器上下发的 HTML 页面是包含当前站点的真实 HTML 结构,对于搜索引擎的爬虫来说会非常容易的匹配到当前关键字。

  • 之后,浏览器会下载当前这份 HTML 的 JS 脚本。

    因为首先呈现给用户的一份静态的 HTML 页面,并不具备任何交互效果。我们需要为页面上的元素增加对应交互,HTML 页面中的 JS 脚本中会包含网站的交互逻辑。

  • 最后,当下载完 HTML 脚本中的 JS 脚本后,自然会执行这些 script 脚本。从而发生一种被称为 # hydrate(水合) 的方式,从而为页面上静态 HTML 元素再次添加对应的事件处理从而保证页面具有交互性。

当 hydration 过程完成后,会由我们的客户端框架接管网站的后续渲染。在后续的导航链接跳转和页面渲染中和服务器已经没有任何关系了,我们完全可以利用客户端的路由切换(History Api/Hash Api)利用 JS 进行页面渲染从而保证切换页面不用再次请求浏览器保证非常及时的页面交互。

1)hydration

上述过程中有一个非常重要的关键字 hydration(水合)。

首次访问页面时,页面的静态 HTML 是在服务端生成的。在服务端我们将生成的静态 HTML 以及 HTML 中携带的 JS 脚本发送到客户端。

此时静态 HTML 会立即显示在用户视野中,然后浏览器会利用网络进程下载当前 HTML 脚本中的 JS 脚本。

当 JS 脚本下载完成后,会立即执行同时发生一种被称为 hydration 的过程。

所谓的 hydration 简单来说,也就是客户端下载完成 JS 脚本后,浏览器会执行下载的 JS 脚本这些脚本中有部分内容会将已经存在的 HTML 内容通过执行下载的 JS 脚本添加上对应的事件监听器从而保证页面的交互。

注意,在 React、Vue 中 hydration 并不意味着重新渲染。因为在 Server 端已经渲染了和 Client 完全相同的 DOM 结构所以完全没有必要在此重新渲染。

所以 hydration 的过程是给当前页面中已经生成的 HTML 页面添加上对应的事件监听器。

这也是为什么在 Next 等框架中为什么必须要保证 Server 端和 Client 的渲染 HTML 结构必须一致的原因。

比如我们以 Next 举例来说(Vue 也是同样的道理):

  • 当用户访问 www.trip.biz 时,服务端接收到请求调用 ReactDOMServer.renderToString() 生成当前页面的 HTML 静态结构。

  • 服务器会下发这个 HTML 页面给客户端,同时这个 HTML 页面上也会携带一部分 JS 脚本 script 标签。

  • 用户的浏览器中会立即展现到该 HTML 页面,同时也会下载对应 JS 脚本并执行。

  • 当 JS 脚本执行完毕后,客户端会调用 ReactDOM.hydrate() 发生水合为当前页面的 HTML 页面添加事件交互处理,同时后续由 JS 接管页面的跳转渲染。

针对于第一步 Next 中存在 Automatic Static Optimization 的优化,并不一定会在每次访问时调用 renderToString 方法,有可能在构建时也会直接生成对应的 HTML 模版。

当然,在最新的 Next 版本中已经支持了Stream以及 Server Components。

整个过程就像是这张图中的样子:

f45ab2c871dc42bc94df5e4f4de06120.jpeg

2)优势

简单聊过了所谓 SSR 的原理后,如果你有认真看上述的内容。其实我相信相较于 CSR ,SSR 这种方式的好处不言而喻:

  • 更好的搜索引擎优化 SEO 方式,HTML 模板是从服务端直接下发这也就导致搜索引擎爬虫中更多的关键字匹配。

  • 更快的首屏渲染,因为相较于 SPA 它少了在 Client 中下载和执行 JS 脚本后渲染的过程。

  • 页面不需要 JS 也可以正常渲染,虽然没有 JS 意味着页面失去了可交互性。但对于禁用 JS 的用户来说,展示一些静态内容总比 SPA 应用的白屏来的更加友好一些对吧。

3)劣势

当然,任何技术方案在不同场景下也存在它自己的不足。

  • 强依赖于服务。

    针对于 CSR 的方式它是一种纯静态资源。我们可以直接将它放在 CDN 上就可以良好的用户访问到,而 SSR 的方式必须依赖于一个服务器进行服务端预渲染。(当然纯 SSG 应用我们不在这个讨论范围之内)

    同时,有服务的地方就存在并发压力。当你需要为你的应用考虑服务端渲染的方式时,一定不要忘记为你的服务器进行压测。

  • Time to Interactive 可交互时间 (TTI) 的增长,虽然说 SSR 的方式有效的缩短了首屏加载的方式,但是会增加所谓的TTI(可交互时间)。

    所谓的 TTI 指标测量页面从开始加载到主要子资源完成渲染,并能够快速、可靠地响应用户输入所需的时间。

    因为 SSR 的方式在用户访问时会下发当前页面中静态的 HTML 内容,也就是所谓的 First Contentful Paint 首次内容绘制 (FCP) 会非常快速,但是页面需要用户交互效果又需要下载和执行完成 JS 脚本发生 hydatrion 后才具有交互性。

    这也就造成页面的 TTI 相较于 CSR 方式会有所差劲,因为 CSR 在渲染完成后就会立即具有交互性(不需要其他任何多余步骤)。

1.3 qwik

上述聊了那么多前置内置,终于要和大家切入正题了。

所谓磨刀不费砍柴功,上边和大家强调现阶段 SSR 的方案以及对应的优劣势就是为了引入下面的内容。

首先,这篇文章的目的是为了让大家在当前众多 SSR 框架中思考性能方面是否可以有所提升的,在服务器方面不会过多的深入。

我们可以稍微思考下上述服务器端渲染的过程:

f17bb0b5a0e0da88bc36b80e27b01afa.jpeg

第一步我们需要在服务端获取对应页面的 HTML 页面,大多数情况(非纯静态页面)就需要在服务端掉用对应渲染方法渲染出 HTML 页面。

那么,如果我们能在第一步渲染 HTML 页面时,就添加对应的事件处理。后续的 3 步是不是完全可以省略下来了对吧。

其实社区内部之前已经有非常多的方案来提升所谓 SSR 框架的性能方案。

比如 Remix 的 HTTP stale-while-revalidate 缓存指令

比如 astro 等新兴框架的 Islands 架构方案,关于 Islands 有兴趣的朋友可以参考神三元的这篇 Islands 架构原理和实践。

针对于上面的概念,我们直接来看看 qwik 中提到的 Hydration is Pure Overhead (完全多余的 Hydration)。

1)Hydration 造成的开销

首先针对于 Hydration 的过程,我们提过到首先会在服务器上进行一次静态 HTML 渲染,之后当 HTML 下发到客户端后又会再次进行 hydrate 的过程,在客户端进行重新执行脚本添加事件。

Hydration 过程的难点就在于我们需要知道需要什么事件处理程序,以及将该事件处理程序附加在哪个对应的 DOM 节点上。

这个过程中,我们需要处理:

  • 每一个事件处理程序中的内容,绝大多数框架中的状态都作为闭包函数保存在内容中。所以需要 hydration 的过程来重新获取状态。

  • 其次,在搞清楚了每个事件处理函数的内容后。我们也需要将对应的事件处理函数附加到对应的 DOM 节点上,同时还要确保该监听器的正确事件类型。

更加复杂每个事件处理函数中的内容是一个闭包函数,这个函数内部需要处理两种状态,APP_STATE 以及 FRAMEWORK_STATE。

  • APP_STATE:应用程序的状态。简单来说应用程序的状态就是 HTML 事件中的各个状态事件,如果不存在这些事件状态那么所有的内容都是没有任何交互效果的。

  • FRAMEWORK_STATE:框架内部状态。通常我们会利用诸如 React 或者 Vue 等框架进行接替渲染。如果没有 FRAMETER_STATE,框架内部就不知道应该更新哪些DOM节点,也不知道应该在什么时候更新它们。

通俗来说 Hydration 就是在客户端重新执行 JS 去修复应用程序内部的 APP_STATE 以及 FRAMEWORK_STATE。

同样还是这这张图:

b1634d5ad3feaef44aaf1e62e285d229.jpeg

在图中的前三个阶段可以被称为 RECOVERY 阶段,这三个阶段主要是在重建你的应用程序。

当从 Server 端下发的 HTML 静态页面后,我们希望它是具有交互效果的 HTML 正常应用程序。

那么此时 hydartion 的过程必须经历下载 HTML 、下载所有相关 JS 脚本、解析并且执行下载的 JS 脚本。

RECOVERY 阶段是和 hydartion 的页面的复杂性成正比,在移动设备上很容易花费 10 秒。

由于RECOVERY是昂贵的部分,大多数应用程序的启动性能都不是最佳的,尤其是在移动设备上。

前三个阶段被称为 RECOVERY 的阶段其实是完全没有必要的,因为在服务端我们已然渲染过对应的 HTML ,但是为了应用程序的可交互性以及服务端仅保留了静态的 HTML 模版导致不得不在 Client 上继续执行一次 Server 端的逻辑。

总而言之,hydration 其实是通过下载并重新执行 SSR/SSG 呈现的 HTML 中的所有 JS 脚本并执行来恢复组建中的事件处理程序。

同一个应用程序,会被发送到客户端两次,一次作为 HTML,另一次作为 JavaScript。

此外,框架必须立即执行 JavaScript 以恢复在服务器上被丢掉的 APP_STATE和FRAMEWORK_STATE。所有这些工作只是为了检索服务器已经拥有但丢弃的东西!!

比如这样一个例子:

export const Main = () => <>
   <Greeter />
   <Counter value={10}/>
</>


export const Greeter = () => {
  return (
    <button onClick={() => alert('Hello World!'))}>
      Trip Biz
    </button>
  )
}


export const Counter = (props: { value: number }) => {
  const store = useStore({ count: props.number || 0 });
  return (
    <button onClick={() => store.count++)}>
      {store.count}
    </button>
  )
}

上边的例子中我们编写了一个 Counter 的计数器组件,在传统 SSR 过程中该组件会被渲染成为:

<button>Greet</button>
<button>10</button>

可以看到上边的两个按钮不拥有任何处理状态的能力。

要使网页具有交互性,必须要做的就是通过下载对应 HTML 页面中的 script 脚本并执行代码从而恢复按钮上的交互逻辑和状态。

为了具有交互性,客户端不得不执行代码实例化组件后重新创建状态。

当上述过程完成后,你的应用程序才会真正具有可交互性。无疑,同一个组件的渲染逻辑被执行了两遍,这是一个非常冗余且耗费性能的过程。

2)Resumability: 更加优雅的 hydartion 替代方案

所以为了消除额外的开销,我们需要思考如何避免重复的 RECOVERY 阶段。同时还要避免上面的第四步,第四步是执行脚本后给现有的 HTML 附加正确的事件处理程序。

qwik 中提出了一个全新的思路来规避 RECOVERY 带来的外开销:

  • 将所有必需的信息序列化为 HTML 的一部分。

    qwik 将需要的状态以及事件序列化保存在 Server 端下发的 HTML 模版中,需要序列化信息需要包括WHAT(事件处理函数内容), WHERE(哪些节点需要哪些类型的事件处理函数), APP_STATE(应用状态), 和FRAMEWORK_STATE(框架状态)。

  • 依赖于事件冒泡来拦截所有事件的全局事件处理程序。

    qwik 中事件处理程序是在全局处理的,这样我们就不必在特定的 DOM 元素上单独注册所有事件。

  • qwki 内部存在一个可以延迟恢复事件处理程序的工厂函数。

    该工厂函数主要用于处理 WHAT 阶段,也就是用来识别某个事件处理函数中应该存在什么脚本逻辑。

4fbc64a39ef9c393228be0b51c402be3.jpeg

我们可以看到所谓的 Resumable 对比 Hydration 明显可以省略不需要后三个阶段,直接获取 HTML 后页面其实就已经准备完毕,这无疑对于性能的提升是巨大的。

对比传统的 hydration 方案,在客户端获得服务端下发的 HTML 后会立即请求需要的 JS 脚本并执行从而为页面附加对应的交互效果。

而 qwik 提出的概念恰恰相反,获取完服务端下发的 HTML 页面后所有的交互效果实际上都是一种惰性创建的效果。

因为我们在 HTML 中的每个元素中都已经通过序列化从而在它的标签属性上记录了对应事件处理函数的位置以及脚本内容(自然内容中也包含对应的状态),所以当获得 HTML 页面后其实就可以说此时页面已经加载完毕了而不需要任何实时的 JS 执行。

这样做的好处是在 qwki 中完全可以省略 hydration 的多余步骤,甚至可以说完全抛弃了 hydration 的概念。

客户端完全不必和服务端的 HTML 进行水合,相同的渲染内容仅仅是在 Server 端进行一次渲染客户端即可拥有对应的事件处理内容。

简单来讲Qwik的工作原理就是在服务端序列化 HTML 模版,从而在客户端延迟创建事件处理程序,这也是它为什么非常快速的原因。

3)qwik 工作机制

上边我们讲到了 qwik 的原理部分,同样拿上边的计数器的例子我们来对比下:

export const Main = () => <>
   <Greeter />
   <Counter value={10}/>
</>


export const Greeter = () => {
  return (
    <button onClick={() => alert('Hello World!'))}>
      Trip Biz
    </button>
  )
}


export const Counter = (props: { value: number }) => {
  const store = useStore({ count: props.number || 0 });
  return (
    <button onClick={() => store.count++)}>
      {store.count}
    </button>
  )
}

在 qwik 编译后,服务端会序列化对应组件的 HTML 结构从而下发如下的模板:

<div q:host>
  <div q:host>
    <button on:click="./chunk-a.js#button">Trip Biz</button>
  </div>
  <div q:host>
    <button q:obj="1" on:click="./chunk-b.js#count[0]">10</button>
  </div>
</div>
<script id="qwikloader">/* qwik 中设置全局事件监听器的代码 */</script>
<script id="qwik/json">/* 用于反序列化的 JSON 相关信息 */</script>

我们可以看到经过 qwik 编译后的 html 结构并不单单只有 DOM 元素,同时会在对应需要状态 & 事件的 DOM 元素上通过 HTML 元素属性来记录当前元素的事件和状态信息,这既是 qwik 中的序列化。

比如上边 button 的 on:click 属性记录了该元素后续需要恢复的所有信息。

需要注意的是序列化这一步是在服务端渲染时完成的,这也就意味着后续客户端可以通过服务端序列化的属性信息进行反序列化从而达到所谓的可恢复性而不需要重复执行组件。

当然你可能会好奇 qwik 是如何进行这些事件 & 状态的恢复,qwik 正是通过在返回的 HTML 页面中内嵌的所谓 qwikloader 的 script 脚本(这段脚本的大小不超过 1kb)配合 qwikjson 映射表,从而在全局进行恢复事件和状态的逻辑。

正因为这个原因,使得 qwik相较于传统 SSR 的 hydration 在 Client 中再次执行渲染从而水合页面状态和事件处理程序,这简直可以说是接近零 JS 的执行过程。

最终在用户触发事件时候达到惰性的创建事件并执行,这个过程中完全没有重复任何服务器已经完成的任何工作。

整个工作过程就像下面这张图描述的那样:

2832735199b7939846584e4da7445285.jpeg

上边的这张图完美的描述了 qwik 的工作原理,相信经过上述的描述大家对于这张图中想表达的思想已经可以完美的理解了。

利用 qwik 的这个优势,在绝大多数应用中我们可以利用 qwik 保证你的 SSR 应用在保证快速的 FCP 的前提也同样拥有与之不相上下的 TTI 体验效果。

4)惰性加载脚本会影响用户交互体验吗

当然上文说过任何框架的优势和劣势都不是绝对的,在我们看来 qwik 的确会存在以下一些问题。

大多数同学看完上边的内容我相信也会存在“惰性加载脚本会影响用户交互体验吗”这样的疑问。

首先,qwik 中既然选择在触发用户行为时,再惰性加载并执行响应的 JS 脚本。那么难免需要在用户触发交互时动态生成对应的事件处理函数进行执行。

这样的方式相较于传统 hydration 的确会存在一些不足,需要额外生成事件会额外造成交互响应时间的损耗而传统 SSR 方式在页面首次加载时就已经绑定好(相当于生成了)相应的事件处理函数。

就惰性加载生成事件这点:

针对于动态加载 JS 脚本,其实已经存在诸如非常多的 prefetch 等等预加载技术。

无论是基于传统 Next 方案还是基于 qwik 这种惰性可恢复的方案,利用 prefetch 等预加载技术优先在网络空闲时加载响应重要的 JS 脚本都是非常有必要的,所以这点在我看来并不是特别重要的问题。

5)延迟加载会带来 bundle 数量的上升吗

qwik 推崇的延迟加载其实已经是一项非常成熟的构建技术了。无论是使用 webpack、rollup 又或是其他任何构建工具都存在延迟加载 & 代码分割的技术。

传统构建工具中关于代码分割会带来以下两点的困难:

  • 需要开发人员自行去处理更加细粒度的代码分割,当然这并不是最主要的。因为目前我们可以利用 Magic Comments 配合 Dynaic Imports 来解决需要手动切入多个入口点的问题。

当然,这一系列事情比起魔法注释。因为 qwik 本身提倡的就是所谓的延迟加载,所以在框架内部已经帮我们足够智能的去处理这个过程。

但是需要注意的是这并不意味着开发者无法自主去控制这个过程。只是在使用框架的过程中,qwik 希望开发者更加专注于他们自身的业务逻辑。

  • 当存在非常多的延迟加载时,传统构建工具会从一个大 bundle 分割成为无数个小的 bundle 。

延迟加载模块的确会存在多个 small bundle 的问题,可是当我们拥有的 bundle 越多,其实我们就拥有更多的自由度去以各种各样的方式去拼装成为单个大的 bundle。

qwik 中存在足够的方式提供给我们将多个小的 chunk 自由组合成为一个从而有效的减少细碎 chunk 的数量,当然这个点在传统构建工具中也是这样。

6)动态创建事件函数会造成内存泄漏吗

qwik 的设计思想在与每次事件触发时通过 qwikloader 来动态创建事件处理函数,相信有的同学存在疑问“那么多次触发事件会造成额外的开销吗”。

qwik 的作者 miško hevery 在 Hydration is Pure Overhead 中明确的表示过 qwik 会在每次事件执行完毕后释放函数,相当于每次事件执行完毕都会进行一次“去水合”的过程。

所以,当你触发一次事件和无数次事件函数在执行过程中对于内存占用来说是相差无几的。

当然相较于传统 hydration 的方式(在页面首次渲染时在内存中记录所有状态),无疑 qwik 这种并不在内存中记录任何状态的方式恰恰对于内存的占用比 dyration 更加轻量化。

7)qwik 真的有那么快吗

说了那么多,那么 qwik 真的有那么快吗。

8f0b785a8d52b817d15332e2b7253e21.jpeg

上图是利用 qwik 搭建的 builder.io 官方网站,我相信 builder.io 的数据已经告诉我们答案了。

固然上述的数据并不仅仅只是单纯一个 qwik 框架带给网站的优化,一定会有代码层面或者构建层面等等方面的优化配合而来的数据。但是针对于 FCP 和 TTI 时间上的一致性这在一个中型 SSR 应用程序其实可以称得上是非常优秀了,我相信这足以说明了 qwik 的确名副其实。

二、结语

我们可以看出来,qwik 的核心思路还是通过更加细粒的代码控制配合惰性加载事件处理程序以及事件委托来缩短首屏 TTI。

文章中我们也讲到了 qwik 其实并不是因为使用了多么牛逼的算法导致它有多么快,而它的速度正是得益于它的设计思路,省略了传统 SSR 下首屏需要加载庞大的 JS 进行 hydration 的过程。

当然,我们对于 qwik 也仍是在学习阶段。后续会在公司里的更多项目尝试 qwik 之后也会和大家分享关于它的更多心得。

总而言之,qwik 的“无水合”设计思路目前看来的确会在框架层面带来巨大的性能提升。大家如果有机会的话也可以在项目中尝试一下 qwik ,相信会给你带来意想不到的收益效果。

【推荐阅读】

1301bc5f75863cbff2aa89edbe33c146.jpeg

 “携程技术”公众号

  分享,交流,成长

合成孔径雷达(SAR)的常见工作模式 随着星载SAR技术研究的深入发展,单一的条带模式已经无法满足当今时代的需求,因此许多新的工作模式相继被提出。这些新模式在分辨率和测绘宽度等方面都有所提高,接下来将简要介绍几种常用的工作模式。 阅读详情

相关推荐

PID算法(位置式pid算法和增量式pid算法)

PID 算法是闭环控制系统中常用的算法,PID 分别是 Proportion(比例)、Integral(积分)、Differential(微分)的首字母缩写。它是一种结合比例、积分和微分三个环节于一体的闭环控。

m0_57678852的博客 2万+

针对开发者的21款移动开发框架

随着移动互联网的持续升温,企业选择开发对应的webapp网站已经成为了必要。下面笔者收集了21款针对开发者的移动开发框架,基于它们可以快速开发一个webapp网页或者hybridapp混合app,或者一些其他好玩的运用。 1.Fries Fries是一款稳定的HTML-CSS-JS框架,用于在实际项目和原型设计中创造类似于Android的原生UI界面。该框架包含所有的重要组件,比如Form、工

ones123654的专栏 1261

VSCode+ESP-IDF开发环境搭建:从零开始创建你的第一个物联网项目(2024最新版)

本文详细介绍了如何在2024年使用VSCode和ESP-IDF搭建物联网开发环境,从零开始创建第一个物联网项目。内容包括环境准备、ESP-IDF配置、项目创建与结构解析、构建烧录步骤以及高级技巧和常见问题解决方案,帮助开发者快速上手ESP32开发。

weixin_29165725的博客 330

【亲测免费】 探索科技新星:Hiwara - 一款高效、智能的Web应用框架

探索科技新星:Hiwara - 一款高效、智能的Web应用框架 项目简介 是一个新兴的Web应用程序开发框架,旨在提供快速、简洁和易于维护的编码体验。它的设计目标是简化前后端分离的工作流程,使开发者能够更专注于业务逻辑,而非基础设施的搭建。Hiwara以其创新的技术栈、高效的性能和丰富的功能集,吸引了众多开发者关注。 技术分析 Hiwara采用了现代化的前端技术和后端架构: 前端:基于Reac...

gitblog_00083的博客 1843

SAP PI实战:5分钟搞定REST适配器同步接口配置(含Postman测试技巧)

本文详细介绍了如何在SAP PI中快速配置REST适配器同步接口,包括ESR设计、集成流配置及Postman测试技巧。通过实战步骤和关键参数设置,帮助开发者高效实现系统集成,特别适合需要实时数据交互的业务场景。

weixin_33738555的博客 485

HSTS漏洞(缺少Strict-Transport-Security头)

HTTP严格传输安全性(HSTS)告诉浏览器只能使用HTTPS访问网站。检测到您的Web应用程序未实现HTTP严格传输安全性(HSTS),因为响应中缺少严格传输安全性标头。理想回复响应头因存在:Strict-Transport-Security: max-age=31536000信息。nginx添加响应头。

墨痕诉清风的博客 4408

体验Vue3的SSR框架 - Nuxt3

为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。

老司机的后备箱 4425

【R-terra包|第一节】- 栅格相关性、散点图 、波段的计算与异常值处理

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、pandas是什么?二、使用步骤1.引入库2.读入数据总结 —```mermaid flowchat st=>start: 开始 e=>end: 结束 op=>operation: 我的操作 cond=>condition: 确认? st->op->cond cond(yes)->e cond(no)->op 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能.

地理空间科学的博客 5614

前端SSR框架(Next、Nuxt)利用宝塔面板部署

SSR服务端渲染的框架部署区别于常规的CSR项目的部署,并不是打包之后访问某个文件就行,而是需要在服务器中运行项目之后访问某个地址,无论是基于Vue的Nuxt.js框架还是基于React的Next.js框架道理都是一样的。Nuxt项目将打出来的包(.nuxt)和nuxt.config.js、package.json、package-lock.json、static文件夹、public文件夹以及一些配置文件打成压缩包放在服务器项目根目录。完成后启动就大功告成了!通过第我们安装的PM2应用可以完成这一配置。

m0_49083276的博客 3344

【AutoSAR】【EcuM】ECU状态管理

目录 一、EcuM架构位置 ​二、EcuM功能介绍 三、EcuM状态机 1.STARTUP阶段 2、UP状态 3、shutdown状态 4、休眠状态 5、OFF状态 一、EcuM架构位置 EcuM模块位于系统服务层,如下图红色方框里; 二、EcuM功能介绍 EcuM本身它管理着ECU在STARTUP, RUN,OFF,SLEEP,WAKEUP状态之间的相互切换。 责所有BSW的初始化以及去初始化 和ComM协作来管理网络状态,在需要时关闭ECU 管理所有的唤醒事件,并且在需要时

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 3354

uniapp [全端兼容] - 详细实现全局修改设置字体大小功能效果,统一修改页面字号字体大小,一键改变字号整个项目立即生效,大中小字号预设、老年人大字模式场景,uniApp全平台兼容控制页面字号大小

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,修改字体大小,一键调整UniApp字体大小,实时改变不用刷新,动态设置字体大小,uniapp全局修改字体字号大小,如何控制全局字号,可调整显示的字体,全项目生效,老年人大字模式,改变所有页面的字体,全局设置字体大小,实现小中大的字体切换,设置改变全局字体大小功能,如何做到全平台兼容,H5APP实现全局字体大小调整,不兼容报错,用户设置字号,全局设置应用字体大小,大中小字体修改,页面设置page-me

🏆 前端领域优质创作者 1万+

SSR:地球上最先进的Serverless渲染框架

`SSR` 是一个专为前端框架在服务端渲染场景下打造的开箱即用的服务端渲染框架。它不仅支持传统的 `Node.js` 应用部署,还完美适配 `Serverless` 环境,实现了服务端渲染规范。`SSR` 框架脱胎于 `egg-react-ssr` 项目和 `ssr` v4版本,通过插件化的代码组织形式,支持任意服务端框架与任意前端框架的组合使用。无论是 `React` 还是 `Vue`,无论是 ...

gitblog_00606的博客 801

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

SSR 框架是什么?

SSR 框架通过服务器端生成 HTML,提升了首屏性能和 SEO 效果,适合内容型网站或需要快速加载的应用。常见的 SSR 框架包括 Nuxt.js、Next.js 等,开发者可以根据项目需求选择合适的工具。

zqzgng的博客 932

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

面试官:说说React服务端渲染怎么做?原理是什么?

但是像一些事件处理的方法,是无法在服务端完成,因此需要将组件代码在浏览器中再执行一遍,这种服务器端和客户端共用一套代码的方式就称之为。浏览器开始进行渲染和节点对比,然后执行完成组件内事件绑定和一些交互,浏览器重用了服务端输出的。结构拼接的页面处理技术,发送到浏览器,然后为其绑定状态与事件,成为完全可交互页面的过程。路径,然后在已有的路由表内查找到对应的组件,拿到需要请求的数据,将数据作为。文件,用于监听3000端口的请求,当请求根目录时,返回。上面的过程中,已经能够成功将组件渲染到了页面上。

linwu的博客 1004

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

SSR+前端框架 项目工程核心

关于SSR的概念和其优缺点,Node.js + Express + Vue3实现SSR的前端项目搭建,服务端server,client客户端渲染。Node服务器端渲染(SSR概念篇),项目介绍,目录。。SSR的实现重点是在服务端生成页面的元素 DOM等返回给浏览器。用前端框架编写app.js脚本,引入框架的组件编写服务器端返回静态html页面的接口在静态html中,加入前端框架 的组件在静态html中,加入前端框架的客户端脚本,使静态页面加入前端框架,实现交互功能。

Azbtt的博客 1665

Pyro Poutine 深度指南:用可组合效应处理器(Effect Handlers)构建概率编程与自定义推断算法

Poutine 是 Pyro 内置推断算法之下的核心基础设施——一组可组合的效应处理器(effect handlers),用于记录、拦截和修改概率程序中每一次 `pyro.sample`、`pyro.param` 等原语调用的行为。Pyro 的几乎所有推断算法(SVI、MCMC、枚举推断等)都是把这些 handler 叠加到随机函数(stochastic function)上构建出来的。读完本文,

gitblog_00617的博客 551

一文讲透Vue3服务器端渲染: 比较SSR和SSG的应用和优势

在本次讨论中,我们探讨了服务器端渲染(SSR)和静态站点生成(SSG)在用户体验、缓存策略、构建与部署、处理动态内容以及安全问题方面的影响和方法。

andy_68147772的博客 5764

工程化与框架系列(17)--SSR服务端渲染

工程化与框架之旅第十七站

欢迎来到这里,希望文章能对你有所帮助 1777

服务器渲染(SSR)-前端框架

服务器渲染(SSR)-前端框架

qq_46344419的博客 1525

Next知识框架、SSR、SSG和ISR知识框架梳理

以下是 Next.js 中 SSR(服务端渲染)、SSG(静态站点生成)、ISR(增量静态再生)等核心概念的面试详解,结合高频考点与实战解析,助你系统掌握技术本质。SSG(静态生成) getStaticProps + getStaticPaths 博客、文档、营销页(内容稳定) 构建时预生成 HTML,CDN 分发,首屏最快。slug].js 匹配动态路径(如 /blog/react-2025)。◦ 核心目标:简化配置(路由、构建、部署开箱即用),提供高性能、SEO 友好的 Web 应用开发体验。

警警的博客 1100

SSR(Server-Side Rendering)项目全面指南

SSR(服务器端渲染)是现代Web开发中的重要技术,它可以改善首屏加载性能、SEO优化和用户体验。下面我将全面介绍SSR项目的关键方面。

linanran1027的博客 3871

vue_SSR框架:搭好的Vue服务器渲染框架,用vue做网站开发、做seo的首选。

vue_SSR框架:搭好的Vue服务器渲染框架,用vue做网站开发、做seo的首选。

江一铭 6025

前端常用框架服务器渲染(Server-Side Rendering,SSR)

SSR 在服务器端执行前端框架(如React、Vue)的代码,生成包含动态内容的HTML页面,客户端接收后直接展示,再通过“注水”(Hydration)绑定交互逻辑。通过框架(Nuxt/Next)的封装,开发者无需手动配置 Webpack 和服务端渲染逻辑,只需专注业务代码即可实现高性能 SSR。:浏览器下载空HTML后,通过JavaScript动态渲染内容,首屏加载慢,SEO不友好。:构建时生成静态HTML,适用于内容固定的场景(如博客),而SSR每次请求动态生成。

s686ttttt的博客 1742

Qwik框架性能优化详解

Qwik框架通过创新的"可恢复性"设计,在服务端渲染(SSR)领域实现突破。其核心是将应用状态序列化到HTML中,客户端无需传统hydration过程,直接从暂停处恢复执行,实现O(1)复杂度的瞬时加载。Qwik支持细粒度按需加载(事件处理器级)、SSR/SSG混合渲染,对React开发者友好。相比传统SSR框架(Next.js/Nuxt.js)和孤岛架构,Qwik避免了hydration开销,实现更极致的性能优化。该框架特别适合对加载速度要求高的内容型网站和大型应用,但需考虑其较新的生

油墨香^-^的博客 430

【Web技术】1525- Qwik-前端性能的终极方案?

出品:西瓜视频前端技术团队作者:张明远 Qwik 是什么 Qwik 是一个前端框架,语法类似 React 使用 JSX 和 Hooks,不过 Qwik 是全栈SSR框架,而且 Qwik 采用了一系列策略优化页面的首屏性能,做的无论应用体积多大,首屏性能 PageSpeed 测试基本都能达到满分 Framework Benchmarks。 Misko Hevery Misko Hevery,Qwik...

pingan8787 3201
上一篇: 携程跨端解决方案的新选择:Taro-CRN
下一篇: 干货 | 提升前端工程化,携程 Design2Code 从零到一的实践
携程技术
博客等级 码龄10年 3716粉丝 324原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值