客户端用法
Lit SSR 生成静态 HTML 供浏览器解析和绘制,无需任何 JavaScript。(不支持声明式 Shadow DOM 的浏览器将需要一些 JavaScript polyfill 来支持使用 Shadow DOM 的 Lit 组件。)对于静态内容的页面,这就是所需的全部内容。但是,如果页面内容需要是动态的并响应用户交互,则需要 JavaScript 来重新应用该响应性。
如何在客户端重新应用响应性取决于你是渲染独立的 Lit 模板还是使用 Lit 组件。
独立的 Lit 模板
Permalink to "独立的 Lit 模板"Lit 模板的"水合"是让 Lit 重新将 Lit 模板的表达式与它们应该在 DOM 中更新的节点关联起来的过程,并添加事件监听器。为了水合 Lit 模板,@lit-labs/ssr-client
包中提供了 hydrate()
方法。在使用 render()
更新服务器渲染的容器之前,你必须首先使用与服务器上用于渲染的相同模板和数据在该容器上调用 hydrate()
:
import {render} from 'lit';
import {hydrate} from '@lit-labs/ssr-client';
import {myTemplate} from './my-template.js';
// 在 render 之前需要进行初始水合:
// (必须使用与在服务器上渲染时相同的数据)
const initialData = getInitialAppData();
hydrate(myTemplate(initialData), document.body);
// 水合后,render 将高效地更新服务器渲染的 DOM:
const update = (data) => render(myTemplate(data), document.body);
Lit 组件
Permalink to "Lit 组件"要重新应用 Lit 组件的响应性,需要加载自定义元素定义以使它们升级,启用它们的生命周期回调,并且需要水合组件 shadow root 中的模板。
升级可以通过简单地加载注册自定义元素的组件模块来实现。这可以通过加载页面的所有组件定义的包来完成,或者可以基于更复杂的启发式方法,其中仅根据需要加载定义的子集。为确保 LitElement
shadow root 中的模板被水合,加载 @lit-labs/ssr-client/lit-element-hydrate-support.js
模块,该模块为 LitElement
安装支持,当它检测到自己使用声明式 shadow DOM 进行了服务器渲染时会自动水合。此模块必须在加载 lit
模块(包括导入 lit
的任何组件模块)之前加载,以确保正确安装水合支持。
当 Lit 组件在服务器上渲染时,它们的 shadow root 内容会在 <template shadowroot>
内发出,也称为声明式 Shadow Root。声明式 shadow root 在解析 HTML 时会自动将其内容附加到模板的父元素的 shadow root 上,无需 JavaScript。
在所有浏览器都包含声明式 shadow DOM 支持之前,可以内联到页面中的一个非常小的 polyfill 是可用的。这让你现在就可以将 SSR 用于任何启用了 JavaScript 的浏览器,并在该功能推出到其他浏览器时逐步解决不支持 JavaScript 的用例。template-shadowroot
polyfill 的用法如下所述。
加载 @lit-labs/ssr-client/lit-element-hydrate-support.js
Permalink to "加载 @lit-labs/ssr-client/lit-element-hydrate-support.js" 这需要在任何组件模块和 lit
库之前加载。
例如:
<body>
<!-- 使用声明式 shadow DOM 渲染的应用组件放在这里。 -->
<!-- ssr-client lit-element-hydrate-support 应该首先加载。 -->
<script type="module" src="/node_modules/@lit-labs/ssr-client/lit-element-hydrate-support.js"></script>
<!-- 随着组件定义的加载,你预渲染的组件将
苏醒并变得可交互。 -->
<script src="/app-components.js"></script>
</body>
如果你正在打包你的代码,确保 @lit-labs/ssr-client/lit-element-hydrate-support.js
首先被导入:
// index.js
import '@lit-labs/ssr-client/lit-element-hydrate-support.js';
import './app-components.js';
使用 template-shadowroot
polyfill
Permalink to "使用 template-shadowroot polyfill" 下面的 HTML 片段包括一个可选策略,在 polyfill 加载前隐藏 body 以防止布局偏移。
<html>
<head>
<!-- 在尚未支持原生声明式 shadow DOM 的浏览器上,在解析了部分或全部预渲染 HTML 后,
但在声明式 shadow DOM polyfill 生效之前,可能会发生绘制。
这种绘制是不理想的,因为它不会包含任何组件 shadow DOM。
为了防止由此产生的布局偏移,我们使用
"dsd-pending" 属性来确保我们只在知道
shadow DOM 处于活动状态后才进行绘制。 -->
<style>
body[dsd-pending] {
display: none;
}
</style>
</head>
<body dsd-pending>
<script>
if (HTMLTemplateElement.prototype.hasOwnProperty('shadowRoot')) {
// 这个浏览器有原生声明式 shadow DOM 支持,所以我们可以
// 立即允许绘制。
document.body.removeAttribute('dsd-pending');
}
</script>
<!-- 使用声明式 shadow DOM 渲染的应用组件放在这里。 -->
<!-- 使用 type=module 脚本,以便我们可以使用动态模块导入。
注意这种模式在 IE11 中不起作用。 -->
<script type="module">
// 检查我们是否需要 template shadow root polyfill。
if (!HTMLTemplateElement.prototype.hasOwnProperty('shadowRoot')) {
// 获取 template shadow root polyfill。
const {hydrateShadowRoots} = await import(
'/node_modules/@webcomponents/template-shadowroot/template-shadowroot.js'
);
// 应用 polyfill。这是一次性操作,所以重要的是
// 它发生在所有 HTML 被解析之后。
hydrateShadowRoots(document.body);
// 此时,没有原生声明式 shadow DOM 支持的浏览器
// 可以绘制你组件的初始状态!
document.body.removeAttribute('dsd-pending');
}
</script>
</body>
</html>
此示例显示了一个策略,结合了 @lit-labs/ssr-client/lit-element-hydrate-support.js
和 template-shadowroot
polyfill 加载,并提供了一个带有 SSR 组件的页面,以在客户端水合。