Lit SSR 服务器使用

此软件包是 Lit Labs 实验软件包系列的一部分。有关在生产中使用 Labs 软件的指南,请参见 Lit Labs 页面。

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

渲染函数的签名是

通常,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 实例(文档即将发布),或者设置为一个空数组以完全禁用自定义元素渲染。

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

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

在全局范围内渲染时,将定义一个共享的 customElements 注册表,并将其与所有渲染请求共享,以及组件代码可能设置的任何其他全局状态。

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

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

当使用全局范围时,您只需使用模板调用 render() 即可获得 RenderResult,并将该结果传递给您的服务器

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

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