“Web Components”的未来

Web Components 似乎要从悬而未决,终于快要被广泛接受了。对前端开发者而言,它们就像 Linux 桌面的那一年一样。我一直在阅读关于 Web Components 的最新文章,希望能找到我错过的某些内容,或者它们现在变得更加实质化,但我总是感到失望。我在2020年撰写了一篇关于 Web Components 的文章,感觉这段时间内关于它们的讨论并没有取得进展。人们似乎总是回到 Web Components 最初的承诺,尽管现实早已表明其未能兑现。

问题在哪里?

总结一下我之前的观点:

  • Web Components 的宣传是“从整个网络获取语义元素!” 但这是试图解决的错误问题。
  • 自定义元素不是“语义化”的,因为搜索引擎不知道它们的含义。
  • “从整个网络获取”对最终用户性能总是比每个站点使用一个一致的、支持渐进增强的 JavaScript 框架更差。
  • customElements.define 是一个非常笨重的 API。
  • <template><slot> 可以,但不能完全替代真正的模板语言。
  • Shadow DOM 也很笨重,解决了一个非常狭窄的问题。
    好了,这些是基础知识,我们能不能就此达成共识呢?
    是的,有些情况下使用 customElement API 是一种方便的方式,可以对事物进行命名空间处理,并确保惰性加载的元素的构造函数被调用,但它们主要用于在富文本内容区域中呈现第三方嵌入内容之类的场景。这并不能构成“Web Components”这一术语指代一个有实际意义的东西。

如果你在基于轻量级框架的 JavaScript 小部件集合上放上“Web Components”的名字,相比于使用其他名字,更多的人会查看它。然而,最终这只是一些笨拙的 DOM API 的市场营销名称,以及我们都希望真的存在的梦想。这个梦想是,你可以轻松混合和匹配小部件,而不考虑每个小部件是用哪个框架编写的,但事实上,这样做的唯一方法是为页面上包含的每个 Web 组件都支付包括一个框架的全部代价。这永远不会是在终端用户性能至关重要的网站上的实际选择。

浏览器支持

好消息是,尽管“Web Components”实际上并不是一个真正的东西,但浏览器制造商最终会以正确的方式解决实际问题,只是有时候需要一些时间。

正如我当时对 Shadow DOM 的描述:

Shadow DOM 的根本作用是允许页面的某个元素拥有自己的 CSS 重置。实际上,我们也可以将这作为 CSS 本身的一部分(也许通过更改 @import 的规则,允许它嵌套而不仅仅是在顶层)。

事实证明,这确实发生了,因此一旦对环形作用域的浏览器支持足够广泛,就没有太多使用 Shadow DOM 的原因了。使用 CSS 作用域选择器和导入层,创建一个仅针对您的组件的 CSS 重置,您将获得所有 Shadow DOM 的好处,而无需关心“light DOM 样式穿透 shadow root”之类的术语。

那么,浏览器制造商应该做的是放更多的努力到“Web Components”本身,而不是什么呢?

我认为,历史上铺设 DOM 的最佳示例就是 jQuery 和 querySelectorAll 之间的关系。在 2003 年,Simon Willison 制作了一个 document.getElementsBySelector 的演示版本。JQuery 将这个想法转化为曾经广泛使用的 $(“”) API。浏览器制造商接受了这个想法,将其变成了 document.querySelectorAll,使其更快速、普遍可用,而不必链接到 jQuery。

这是 Web 进化的理想情景:开发人员在一系列年份内共同努力,找到了解决一个重复问题的方案,然后浏览器制造商将该解决方案变成原生的,以便普遍可用和更高性能。相比之下,customElement 和 Shadow DOM API 大约是在十年前诞生的,早于许多现代 JavaScript 框架的技术。因此,由于当时我们作为一个行业在构建大型 JavaScript 应用程序框架方面的经验不足,它们最终解决了错误的问题。

与其试图改进现有的“Web Components”,浏览器制造商应该专注于找到我们可以标准化开发人员已经在做的新领域。我有三个建议,他们应该关注什么。

近况

最近,Nolan Lawson写了一篇《让我们通过构建一个现代 JavaScript 框架来学习它的工作原理》的文章。在文章中,Lawson将“现代”框架定义为具有以下三个组件:

  • 使用响应性(例如信号)进行 DOM 更新。
  • 使用克隆的模板进行 DOM 渲染。
  • 使用现代 web API,如