Lit SSR 服务端用法

This package is part of the Lit Labs family of experimental packages. See the Lit Labs page for guidance on using Labs software in production.

服务端渲染从使用 @lit-labs/ssr 包中提供的特定于服务器的 render() 函数来渲染 Lit 模板 开始。

render 函数的签名是:

通常,value 是由 Lit 模板表达式产生的 TemplateResult,如:

模板可以包含自定义元素。如果自定义元素在服务器上已定义,它们将依次被渲染,连同它们的模板一起。

要渲染单个元素,你可以渲染一个只包含该元素的模板:

render() 返回一个 RenderResult:一个可以流式传输或连接成字符串的值的可迭代对象。

RenderResult 可以包含字符串、嵌套的渲染结果,或字符串或渲染结果的 Promise。并非所有渲染结果都包含 Promise——这些可能发生在自定义元素执行异步任务时,如获取数据——但由于 RenderResult 可以包含 Promise,将其处理成字符串或 HTTP 响应 潜在地 是一个异步操作。

即使 RenderResult 可以包含 Promise,它仍然是一个同步可迭代对象,而不是异步可迭代对象。这是因为同步可迭代对象比异步可迭代对象更快,并且许多服务器渲染不需要异步渲染,因此不应该为异步可迭代对象支付开销。

在同步可迭代对象中允许 Promise 会创建一种混合同步/异步迭代协议。在消费 RenderResult 时,你必须检查每个值以查看它是否是 Promise 或可迭代对象,并根据需要等待或递归。

@lit-labs/ssr 包含三个工具来为你处理这个问题:

  • RenderResultReadable
  • collectResult()
  • collectResultSync()

RenderResultReadable 是一个 Node Readable 流实现,它提供来自 RenderResult 的值。这可以被管道传输到 Writable 流,或传递给像 Koa 这样的 Web 服务器框架。

当与流式 HTTP 服务器或其他支持流的 API 集成时,这是处理 SSR 结果的首选方式。

collectResult(result: RenderResult): Promise<string>

collectResult() 是一个异步函数,它接收一个 RenderResult 并将其连接成一个字符串。它等待 Promise 并递归到嵌套的可迭代对象中。

示例

collectResultSync(result: RenderResult): Promise<string>

collectResultSync() 是一个同步函数,它接收一个 RenderResult 并将其连接成一个字符串。它递归到嵌套的可迭代对象中,但在遇到 Promise 时 抛出异常

由于此函数不支持异步渲染,建议仅在无法等待异步函数时使用它。

render() 的第二个参数是一个 RenderInfo 对象,用于将选项和当前渲染状态传递给组件和子模板。

调用者可以设置的主要选项有:

  • deferHydration:控制顶级自定义元素是否添加 defer-hydration 属性,以指示元素不应自动水合。默认为 false,因此顶级元素 确实 自动水合。
  • elementRenderers:用于渲染自定义元素的 ElementRenderer 类数组。默认情况下,这包含 LitElementRenderer 来渲染 Lit 元素。可以设置为包含自定义 ElementRenderer 实例(文档即将推出),或设置为空数组以完全禁用自定义元素渲染。

在 VM 模块或全局作用域中运行 SSR

Permalink to "在 VM 模块或全局作用域中运行 SSR"

为了在 Node 中渲染自定义元素,必须首先使用全局 customElements API 定义和注册它们,这是一个仅浏览器特性。因此,当 Lit 在 Node 中运行时,它会自动使用在服务器上渲染 Lit 所需的最小 DOM API 集,并定义 customElements 全局变量。(有关模拟 API 的列表,请参阅 DOM 模拟。)

Lit SSR 提供了两种在服务器端渲染自定义元素的不同方式:在全局作用域中渲染或通过 VM 模块渲染。VM 模块利用 Node 的 vm.Module API,能够在 V8 虚拟机上下文中运行代码。这两种方法主要在如何共享全局状态(例如自定义元素注册表)方面有所不同。

在全局作用域中渲染时,将定义一个单一的共享 customElements 注册表,并在所有渲染请求之间共享,以及组件代码可能设置的任何其他全局状态。

使用 VM 模块渲染允许每个渲染请求都有自己的上下文,该上下文与主 Node 进程有不同的全局。customElements 注册表将仅安装在该上下文中,其他全局状态也将隔离到该上下文。VM 模块是一个实验性的 Node 功能。

全局VM 模块
优点:
  • 易于使用。可以直接导入组件模块并使用模板调用 render()
缺点:
  • 自定义元素在不同渲染请求之间注册在共享注册表中。
优点:
  • 隔离不同渲染请求之间的上下文。
缺点:
  • 使用不那么直观。需要编写并指定带有要调用的函数的模块文件。
  • 由于每个请求都需要重新评估模块图,因此速度较慢。

使用全局作用域时,你可以直接使用模板调用 render() 来获取 RenderResult 并将其传递给你的服务器:

Lit 还提供了一种方法,可以将应用代码加载到单独的 VM 上下文中并从中渲染,该上下文具有自己的全局对象。

注意:使用此功能需要 Node 14+ 并向 Node 传递 --experimental-vm-modules 标志,因为它使用实验性 VM 模块来创建模块兼容的 VM 上下文。