容器

每个 Qwik 应用程序都包含在一个元素中,通常是 <html> 元素。这个元素成为应用程序的容器。容器是应用程序的根元素,所有组件、状态和事件都包含在其中。

<html q:container="paused" q:version="0.12.1" q:base="/build">
  ...
</html>

容器属性

由于容器是由 Qwik 运行时隐式渲染的,所以无法使用 JSX 定义自定义 HTML 属性,但是 SSR 渲染 API(如 renderToStringrenderToStream)提供了 containerAttributes 选项来定义自定义属性:

renderToStream(<Root />, {
  containerAttributes: {
    lang: 'en',
  },
});

上面的代码将渲染以下 HTML:

<html lang="en" q:container="paused" q:version="0.12.1" q:base="/build">
  ...
</html>

在上面的示例中,lang 属性被添加到 <html> 容器元素中。

注意,该属性不会是响应式的,如果应用程序需要动态更改该值,需要通过手动操作 DOM 来实现。

除了自定义属性之外,Qwik 还会自动渲染 q:containerq:versionq:renderq:base 属性。

  • q:container - 容器状态。该属性由 Qwik 运行时用于确定容器是否处于暂停状态。该属性的值为 pausedresumed

  • q:version - Qwik 运行时的版本。

  • q:render - 指示容器的渲染方式。该属性的值为 ssrssr-devdomdom-dev

属性

由于运行时确保容器之间的隔离,多个容器可以在同一个文档中共存,一个容器甚至可以包含另一个嵌套的容器,这个属性允许容器将应用程序分解为更小的部分。

  • resumed:每个容器可以独立于页面上的所有其他组件进行恢复。独立的可恢复性进一步减少了需要恢复反序列化的状态量。
  • updated:可以在任何时候使用 innerHTML 更新/替换每个容器。这允许页面的一部分在不强制重新获取完整 HTML 文档的情况下进行更新,无需下载或执行 JavaScript。
  • compiled:每个容器可以单独编译和部署,与其他容器分开编译尤其适用于大规模应用程序和大规模团队的工作。
  • versioned:每个容器可以运行不同版本的 Qwik 框架。允许从许多小容器组合网站。

容器可以嵌套在树中,并且可以进行通信和共享数据。组件间的通信要求组件具有明确定义的边界,我们称之为容器协议。

<html q:container="paused" q:version="0.12.1" q:base="/build">
  <head>
    <title>我的 Qwik 应用程序</title>
  </head>
  <body>
    <header q:container="resumed" q:version="0.11.1" q:base="https://server.a/build">
      <div>
        <h1>这是一个来自容器的标题</h1>
      </div>
    </header>
 
    <footer q:container="paused" q:version="0.13.0" q:base="https://footer.server.b/">
      <div>
        <h1>这是一个页脚</h1>
      </div>
    </footer>
  </body>
</html>

容器 vs. 组件

容器听起来与组件非常相似;它们有什么区别?你可以将容器视为更受限制的组件。然而,组件可以做一些容器无法做到的事情。

  • 容器只能接收只读属性。这个限制是因为容器的输入可能需要被序列化用于 SSR 请求。
  • 容器不理解内容投影
  • 容器不能修改传入的状态。

组件有一些限制:

  • 组件必须一起编译,因此共享相同的捆绑包和相同的 Qwik 版本。
  • 在暂停时,容器中的所有组件一起进行序列化(然后一起恢复)。

容器解决了什么问题?

容器允许多个独立的 Qwik 应用程序在页面上运行,并对用户表现为单个应用程序。有两种最常见的用例:

  1. 路由
  2. 微前端架构

路由

一个典型的网站由两个逻辑部分组成:

  1. 导航,通常在许多页面上保持不变。
  2. 出口,根据用户导航到的路由而变化的页面部分。

我们可以将这两部分建模为两个导航和出口容器。当用户首次导航到一个路由时,服务器会响应包含导航和出口容器的 HTML。一旦用户导航到第二个路由,有三种方法可以解决导航问题:

  1. 最简单的方法是进行完整的往返并下载一个全新的页面。主要的缺点是应用程序在客户端上失去了所有状态。
  2. 传统的方法是将任何进一步的导航视为 JavaScript 处理。我们用新的出口组件替换当前的出口组件,并让新组件进行渲染。缺点是需要下载和执行 JavaScript。
  3. Qwik 的方法将导航和出口视为两个不同的容器。第一个导航下载表示完整页面的 HTML(包含两个容器)。随后的导航仅获取出口容器的 HTML。这种方法是两全其美的。导航速度快(无需下载或执行 JavaScript),应用程序在父容器中保持其状态。

微前端

当应用程序变得非常庞大时,将其视为单个应用程序变得不切实际。更好的心理模型是许多应用程序共同工作,给用户留下单个应用程序的印象。

对于大型应用程序,团队也变得庞大。大型团队通常有不同的目标,因此有不同的发布计划。

容器允许大型团队将应用程序分解为许多较小的部分,并将每个部分视为具有单独的部署、测试和版本升级计划的单元。

团队将应用程序分解为容器,并明确定义容器之间的协议。只要满足协议,每个团队就可以独立部署这两个容器。

Contributors

Thanks to all the contributors who have helped make this documentation better!

  • the-r3aper7
  • RATIU5
  • adamdbradley
  • manucorporat
  • cunzaizhuyi
  • Craiqser
  • mhevery