容器

每个 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>My Qwik Application</title>
  </head>
  <body>
    <header q:container="resumed" q:version="0.11.1" q:base="https://server.a/build">
      <div>
        <h1>This is a header form a container</h1>
      </div>
    </header>
 
    <footer q:container="paused" q:version="0.13.0" q:base="https://footer.server.b/">
      <div>
        <h1>This is a footer</h1>
      </div>
    </footer>
  </body>
</html>

容器与组件

容器听起来非常像组件;有什么区别?您可以将容器视为限制更严格的组件。但是,组件可以做一些容器做不到的事情。

  • 容器只能具有传递给它们的只读属性。此限制是因为容器输入可能需要为 SSR 请求序列化。
  • 容器不理解 内容投影
  • 容器无法修改传递给它们的状态。

组件有限制

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

容器解决了什么问题?

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

  1. 路由
  2. 微前端架构

路由

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

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

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

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

微前端

当应用程序变得非常庞大时,将其视为单个应用程序变得不切实际。一个更好的思维模型是,许多应用程序协同工作,给用户一种单个应用程序的印象。

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

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

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

贡献者

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

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