渐进式

渐进式是指根据应用程序的需求下载代码,而不是急切地下载整个代码库。

这与 Qwik 的 核心原则 相连,该原则侧重于尽可能延迟 加载 和执行 JavaScript。Qwik 需要将应用程序分解成许多延迟加载的块才能实现这一点。

当前技术水平

现有框架存在两个问题:

  • 延迟加载边界完全委托给开发者
  • 框架只能延迟加载当前渲染树中不存在的组件。

问题在于框架需要将它们内部状态与 DOM 进行协调。这意味着应用程序至少需要进行一次 水合。框架需要能够进行完整渲染以重建框架的内部状态。在第一次渲染之后,框架可以更精确地进行更新,但损害已经造成,代码已经下载。因此,现在出现了两个问题

  • 框架需要下载并执行组件以在启动时重建渲染树。(参见 水合是纯粹的开销)这迫使所有渲染树中的组件急切地下载和执行。
  • 事件处理程序与组件一起提供,即使它们在渲染时不需要。包含事件处理程序会强制下载不必要的代码。

解决方案

Qwik 的架构充分利用了现代工具来自动解决入口点生成问题。开发者可以像往常一样编写组件,而 Qwik 优化器会将组件拆分成块,并在需要时下载它们。

此外,框架运行时不需要下载与交互性无关的代码,即使组件是渲染树的一部分。

优化器

优化器 是一种代码转换,它将函数提取到顶级可导入符号中,这使 Qwik 运行时能够根据需要延迟加载 JavaScript。

优化器和 Qwik 运行时协同工作以实现细粒度延迟加载的预期结果。

如果没有优化器,则

  • 代码必须由开发者拆分成可导入的部分。这将是不自然的编写应用程序方式,导致糟糕的开发体验。
  • 应用程序将不得不加载大量不必要的代码,因为没有延迟加载边界。

Qwik 运行时必须理解优化器的输出。这里需要理解的是,通过将组件拆分成延迟加载的块,延迟加载需求将异步代码引入框架。框架必须以不同的方式编写才能考虑异步性。现有框架假设所有代码都是同步可用的。这种假设阻止了将延迟加载轻松插入现有框架。(例如,当创建新组件时,框架假设其初始化代码可以以同步方式调用。如果这是第一次引用组件,则其代码需要延迟加载,因此框架必须考虑这一点)。

延迟加载

延迟加载是异步的。Qwik 是一个异步框架。Qwik 理解,在任何时候,它可能没有对回调的引用,因此它可能需要延迟加载它。(相比之下,大多数现有框架假设所有代码都是同步可用的,这使得延迟加载变得不 trivial)。

在 Qwik 中,所有内容都是延迟加载的

  • 组件在渲染时 - 初始化块和渲染块
  • 组件任务 - 副作用,仅在输入更改时下载
  • 监听器 - 仅在交互时下载
  • 样式 - 仅在服务器没有提供它们时下载

延迟加载是框架的核心属性,而不是事后才想到的。

优化器和 $

再次看看这个例子

// the `$` suffix for `component` indicates that the component should be
// lazy-loaded.
export const Counter = component$(() => {
  const count = useSignal(0);
 
  // the `$` suffix for `onClick` indicates that the implementation for
  // the handler should be lazy-loaded.
  return <button onClick$={() => count.value++}>{count.value}</button>;
});

注意代码中 $ 的存在。$ 是一个标记,它告诉优化器,它后面的函数应该延迟加载。$ 是一个单字符,它提示优化器和开发者,让他们知道这里发生了异步延迟加载。

贡献者

感谢所有帮助改进这份文档的贡献者!

  • adamdbradley
  • RATIU5
  • manucorporat
  • fleish80
  • msssk
  • mhevery
  • mrhoodz
  • thejackshelton
  • moinulmoin