构想Qwik
从外观或功能上看,Qwik与其他web框架非常相似的。 也是通过渲染一个组件树的方式来实现一个可交互的应用。
但是Qwik和其他web框架不同的地方是:Qwik是怎么实现的。 Qwik的目标是瞬间启动应用,即使在移动设备上。 Qwik通过下面两个主要策略实现这一点:
- 尽可能的延迟下载和执行JS代码。
- 在服务端序列化应用和状态的执行状态,从而在客户端恢复执行。
Qwik是目标是 只需要下载和执行应用最小限度的代码。
核心原则
尽可能的延迟下载和执行JS代码
Qwik应用启动的很快是因为只有一小撮JS代码执行了。(最简单时,一个Qwik应用只需要下载1KB大小的JS即可变得可交互)
通过渐进式延迟加载JS的下载和执行,Qwik可以提供接近瞬时的启动性能,这是当前同类框架所不能的达到的。
Qwik很快不是因为它有什么聪明的算法,而是因为它认为大多数JS代码最终也不需要下载和执行,所以只下载和执行必要的JS就行了。 它的速度来自于(它的设计让它可以)少做很多事(比如hydration),而这些事是其他框框必须要做的(所以他们慢)。
可恢复性(Resumability) & 序列化
关于可恢复性的讨论在这里here。 可恢复性让Qwik应用在服务端渲染完毕以后,在客户端继续执行。 所有框架都需要跟踪关于应用状态的一些内部数据结构。 当前的一批框架不会在服务端保存这些信息然后将其发送到浏览器,这带来的结果是,框架数据结构需要在浏览器上重建。 重建数据结构和给DOM添加事件的过程叫做hydration。
Qwik就不一样了,Qwik在服务端将工作交手给浏览器时,会序列化事件监听器、内部数据结构、以及应用状态到HTML里面。 因为所有信息都在HTML里序列化好了,浏览器就可以继续执行应用了(可恢复性)。
现代应用的问题在哪里?
现代应用或站点需要太多JS才能变得可交互。 太多JS会带来两个问题:
- 网络带宽: 许多JS代码要下载到客户端,在弱网环境下,这可能需要很长一段时间。
- 启动时间: 下载到客户端以后, 代码还需要执行 (hydration的一部分过程) 来使得站点变得可交互。
随着应用的交互越来越多、应用越来越复杂,这些年JS代码数量持续增加且没有减小的趋势。 简单来说,我们的站点越来越复杂,而随着复杂性的增加,就需要写更多的代码,而所有这些新增代码, 都会拉低站点的启动性能。
更糟糕的是,JS是单线程的,因此我们的复杂站点并不能充分利用多核CPU的优势。
我们是怎么一步步走到这里的?
上面两个问题的解决方案是非常明显的,但也是非常难的:减少JS数量。 说明显是因为我们都同意网站的JS越少,网站性能越好。 说难是因为我们的工具不支持让我们减少JS。 几乎所有我们的工具都在解决问题,但与此同时带来更多的JS代码。 这是因为大多数工具大多数工具都是用来解决特定问题的,并没有考虑它(工具)自身也会使网站JS代码量越来越多这件事。
你需要解决渲染、样式、动画、A/B测试、数据分析问题吗?
都有对应的工具给你准备好了。你只需要引入一个<script>
标签,这些工具就能帮你解决特定的问题,但是代价是你的站点的初始bundle更大了。
作为一个产业,我们未能仔细考量bundle size的问题。 每个工具都在单独地解决特定问题,但是bundle size并没有放在天平的另一边进行衡量。 只有当你把越来越多的工具堆积在一个应用里,bundle size的问题才突然显现出来,但此时,已经很少有开发者能为此做什么了。
怎么解决?
Qwik从设计之初就着眼于解决疯涨的bundle size问题。 小的bundle size是Qwik的初始目标(初心),其他的设计决策都要首先屈从于此目标。
但Qwik也不是一个能减少你JS代码量的框架。 它的方式是不需要在应用启动时,把应用的全部JS代码都一次性地下载到客户端。 Qwik是把"尽可能延迟加载和执行JS"理念发挥到极致的产物。
是的,QWIK需要一个不同方式来思考和设计你的应用。 结果是:几乎为0的初始JS量 和 当用户交互时渐进加载和执行其他JS代码。
bundle Size不应该是开发者的问题
今天,bundle Size是开发者的问题。 如果你按照每个框架、工具等的最佳实践来开发,你仍会得到一个很大的bundle size。 等到了bundle size很大的时候,开发者开始用一些懒加载技术缓解这个问题。 (但是所有试过这些技术的人都会告诉你,那些技术(对解决bundle sized过大问题)起到的作用非常有限)
我们行业的最佳实践就是会导致很大的bundle size,这样的例子在整个web界随处可见。
Qwik的理念是bundle size不应该是开发者要解决的问题,而应该作为框架设计的一部分,是框架要解决的问题。
Qwik从框架底层设计了许多可以懒加载的边界。可以把你的应用拆分成许许多多的chunks,应用运行的时候只需要按需加载这些chunks即可。
为什么不改造现有框架或工具?
简言之,懒加载哲学是比较底层的,不太可能在不从根本上改变现有框架/工具的基础上添加进去。 这样根本性的改变是和现有的框架/工具以及他们的生态不兼容的。
当一个框架做了一个假设,比如所有渲染都是同步的,添加异步的懒加载基本上不可能。 又或者,一个框架为了使页面可交互,就要从组件模板里恢复事件监听器,然后就必须下载和执行所有组件代码。 这里只有举了两个例子,实际上,还有许许多多其他理由,使得当前框架的心智模型不具备 改造为可恢复性的框架 的条件。
上述理由意味着现有框架添加可恢复性作为一个特性基本上是不可行的。 现有框架绝无可能做到目前Qwik所做到的(除非做 破坏性向后兼容)。
为什么要推出Qwik?
因为我们相信有更好的构建站点的方式。
一种不需要在应用启动时就要急切地下载大量JS才能使站点可交互的方式。
一种让开发者安心开发业务功能而不是还要让他们发愁拆分巨大代码库为小chunks的方式。
一种可以拥有 瞬间启动且拥有更好的用户体验的站点 的方式。
而所以以上这些优点,都是与仓库代码量无关的,即无论你的总代码量有多大,上述优点都应该一直保持。