我经常听到的一个主要抱怨是关于 web 组件不支持服务端渲染。这其实有点误导性,因为这只是部分正确。你瞧,这里的服务端渲染其实有两种。在一种情况下可以工作,但在另一种情况下则不行。别担心,我来解释一下,你就会明白了。 😄
服务器渲染实际上有两种类型的服务器端渲染往往被混淆在一起。第一种类型是服务器端框架渲染,第二种类型是客户端框架渲染。
服务器端渲染框架 SSR
SSR(服务器端渲染)框架是指你使用一个完全在服务器上运行 HTML 模板逻辑的框架来生成用于在浏览器中渲染的 HTML。这些框架包括但不限于 Ruby on Rails、ASP.Net、PHP,以及使用 Pug 或 EJS 等模板语言的 Node.js 框架。
这种服务器端渲染方式非常适合Web组件!
SSR 客户端框架
客户端渲染的服务器端渲染(SSR)客户端框架是指前端框架在发送给浏览器之前,在一个 Node.js 服务器上执行客户端代码。这样做的目的是为了减少发送到浏览器并在浏览器中执行的 JavaScript 量。
这样做能带来几个好处:
- 提升性能
- 更出色的SEO
- 降低对JavaScript的依赖
问题是,这种做法给自定义元素和其他Web API带来了一些挑战。
第一个问题是,在定义自定义元素时,API 是 window.customElements.define('my-element', MyElement)
。当你在 Node.js 服务器上渲染客户端代码时,猜猜看少了什么——window
。因此,像 window
对象 以及 localStorage
和 MutationObserver
这样的其他 API 在 SSR 时会无法使用。
另一个挑战是,web 组件是互操作的,这意味着它们可以跨框架使用,就像标准 HTML 元素一样,但客户端框架的 SSR 并没有遵循任何标准。每个框架都有自己独特的处理 UI 的方法,因此没有明确的方法来决定何时以及如何进行 SSR。你可能需要针对每个使用环境分别实现 SSR。
现在的解决方法你现在就可以让你的 web 组件在全页渲染(SSR)的客户端框架中使用。
推迟定义
首先,你可以让组件正常工作的第一步是将组件定义推迟到 window
对象存在之后。不幸的是,因为在服务器上执行的逻辑可能不会在代码到达客户端时再执行,所以在定义组件之前检查 window
是否存在并不能始终如一地工作。大多数框架都有指定代码仅在“客户端”运行的方法,例如在某些框架中可能是这样的。因此,你需要根据你所使用的框架来找出如何实现这一点。
声明式Shadow DOM(Shadow DOM)(DSD)
最近的一个进展是能够在阴影根中声明性地定义 HTML 模板。这种技术被称为声明性阴影 DOM(declarative shadow DOM)。
<my-button>
<template shadowrootmode="open">
<style>
button {
padding: 0.25rem;
border: solid 1px black;
}
</style>
<button>
<slot></slot>
</button>
</template>
我的按钮
</my-button>
全屏模式 退出全屏
这提供了非常惊人的功能,如果你将组件的定义延后,当客户端准备好了时,它们就可以升级。缺点是它对于像含有许多组件的设计系统来说,扩展性较差。你得对页面上的每个自定义元素都这么做。
<my-button>
<template shadowrootmode="open">
<style>
button {
padding: 0.25rem;
border: solid 1px black;
}
</style>
<button>
<slot></slot>
</button>
</template>
按钮1
</my-button>
<my-button>
<template shadowrootmode="open">
<style>
button {
padding: 0.25rem;
border: solid 1px black;
}
</style>
<button>
<slot></slot>
</button>
</template>
按钮2
</my-button>
全屏模式 退出全屏
团队现在正尝试将其作为临时措施使用(就像@lit-labs/ssr一样)。这通常需要对代码进行特别考虑,比如在何时何地使用哪些API都有限制,所以我认为这不是一个理想的解决方案。
WASM? (WebAssembly?)
来自Enhance团队的一个有趣的新型解决方案是他们正在使用WebAssembly来提供自定义元素的SSR(服务器端渲染)。目前这种做法仅限于他们的生态系统内,但未来有机会从中学习并尝试在未来创建一种更通用的框架无关的解决方案。
未来可能的解决办法有一些新的想法正在酝酿中,应该能提供一个可扩展的解决办法来解决在SSR处理Web组件时遇到的一些难题。
声明式自定义元素(声明式自定义元素,DCE)
声明式自定义元素 (DCE) 可能提供一种更高效的方式来编写 web 组件的技术手段。这类似于使用声明式 Shadow DOM 的自定义元素,只需定义一次,即可在任何地方重复使用。
<template element="自定义按钮">
<style>
button {
padding: 0.25rem;
border: solid 1px black;
}
</style>
<button>
<slot></slot>
</button>
</template>
<自定义按钮>My Button 1</自定义按钮>
<自定义按钮>My Button 2</自定义按钮>
全屏显示 退出全屏
结合HTML模块,这将为自定义元素提供一种机制,使其既适用于客户端框架SSR友好,也能够降低对JavaScript的依赖,并提高不需要JavaScript的自定义元素的性能。此外,就像使用声明性Shadow DOM的自定义元素一样,这些自定义元素在客户端可用时可以升级,以支持更高级的用户交互。
结尾如果你的应用使用服务器端框架来渲染你的UI,你可以放心地使用Web组件。如果你使用客户端框架来渲染你的UI,你可以现在做一些调整,使你的组件在这种情况下更好地运行,但有一些新的东西即将到来,这将大大提升SSR下自定义元素的体验。
共同学习,写下你的评论
评论加载中...
作者其他优质文章