戴夫·鲁珀特最近在他的文章《如果 Web 组件真的很棒,为什么我不在使用它们?》中引起了一些轰动。我已经使用 Web 组件工作了几年,所以我想对此发表一些看法。
冒着给出最典型的“视情况而定”答案的风险,我认为 Web 组件有优点和缺点,你必须在决定何时使用它们之前了解权衡。因此,让我们先探讨一些 Web 组件真正发挥优势的情况,然后再看看它们可能不适用的地方。
客户端渲染的子组件
对我而言,这是 Web 组件最明显的成功用例。你有一些位于 DOM 树末端的组件,它不需要在服务器端渲染,也不在内部使用
在这一点上,你已经避开了一堆 Web 组件的棘手问题,比如服务器端渲染(SSR)
、注入(hydration)
、插槽(slotting)
,甚至可能还有虚拟DOM。如果你不使用框架,或者你使用的Web 组件框架,你只需将
举个例子,以我的 emoji-picker-element 为例。导入它只需一行 HTML:
1 | <script type="module" href="https://cdn.jsdelivr.net/npm/emoji-picker-element@1/index.js"></script> |
1 | <emoji-picker></emoji-picker> |
没有打包工具、没有转译器、没有框架集成,只需复制粘贴。这几乎就像是 jQuery 插件的古老时代。然而,我也看到它在复杂的单页面应用项目中被使用,Web 组件可以适用于各种情况。
这几乎是你能够接近 Web 组件最初愿景的地方,即使用 <fancy-element>
应该和使用内置的 HTML 元素一样简单。
兼容代码,或避免大规模重写
想象一下:你有一个庞大的 React 代码库,它在一段时间内一直为你提供良好的服务,但现在你的团队想要转向 Svelte。是时候重新编写整个代码了,对吧?包括找到每个第三方组件的新 Svelte 版本?
这是很多前端开发人员在从一个框架切换到另一个框架时考虑的方式,其中包括庞大的切换成本。我见过的关于 Web 组件的最大误解是,它们只是同一个故事的另一种风格。
实际上不是这样的。Web 组件的整个目的是使我们摆脱这种频繁变化。如果你决定从 Vue 切换到 Lit,或从 Angular
切换到 Stencil
(或其他框架),如果你一次性重新编写所有组件,那么你就会面临很多不必要的痛苦。
只需让旧代码和新代码并存即可。使用 Web 组件作为两者之间的可互操作性层来将它们粘合在一起。你不需要一次性重新编写所有内容:
1 | <old-component> |
Web 组件可以将属性/属性传递下去,并将事件传递回来(这基本上就是它们的全部内容)。如果你的框架支持 Web 组件,那么这将自动起作用。如果不支持,你可以编写一些轻量级的胶水代码。
现在,有些人可能对同一页上存在两个框架的想法感到不安,但我认为这更多是基于直觉而不是基于证据。公平地说,如果你使用一个元框架来进行 SSR/注水,那么这种部分迁移可能比较困难。但是,如果 Web 组件擅长于在客户端定义将两个组件组合在一起的高级契约,那么也许它们是值得考虑的选择,特别是如果你厌倦了每年重写整个用户界面(或者你的老板对你这样做感到厌烦)。
设计系统和企业
如果你观看卡桑德拉·罗伯茨(Cassondra Roberts)在CSS Day的演讲,会看到一个漂亮的幻灯片,上面有很多公司的标志证明了 Web 组件的渗透:
如果这还不够,你还可以看看 Oracle
、SAP
、ServiceNow
等等……名单还在继续。
你会注意到许多大公司(比如我所在的公司)在悄悄地使用 Web 组件,尤其是在它们的设计系统和组件库中。如果你在 Web 开发社交媒体上花费了很多时间,这可能会让你感到惊讶。了解到,按照某些衡量标准,React 在页面加载中的使用率约为 8%,而 Web 组件的使用率为 20%,这也可能让你感到惊讶。
事实是,很多大公司不会在社交媒体上(Twitter/X、Reddit等)努力向你推销 Web 组件或教你如何使用它们。另一方面,在 Twitter 上有很多技术影响者,他们忙于随时了解 React 的每个次要版本和该生态系统的新变化。其原因相当简单:大公司往往在内部沟通很多,但在外部沟通相对较少,而小公司(机构、创业公司、自由职业者等)相对于其公司规模来说在社交媒体上更活跃。因此,如果 Web 组件在企业内部比在外部更受欢迎,你在整天浏览 Twitter 时是永远不会知道的。
那么为什么大企业如此喜欢 Web 组件呢?首先,基于 Web 组件的设计系统可以在各种环境中运行。一个大公司可能在 React、Angular、Ember 和静态 HTML 中编写前端,它们都必须与公司的主题和品牌协同工作。大规模重写(如上文所述)可能对于普通创业公司来说是一项有趣的练习,但在企业世界中实际上并不切实际。
拥有大量代码基的消费者,并需要考虑更长时间跨度,会导致不同的技术决策。对我来说,这指向了企业喜欢 Web 组件的主要原因:稳定性和长寿性。
想象一下你平均的 React 代码库,以及更新任何依赖项(React Router、Redux、React 本身等)可能导致花费数周的工作来重写你的代码以适应所有重大变更。在企业规模下,即使是微小的更改也可能引起 Hyrum’s Law 的出现,即即使是微小的变化也可能导致数千个组件的破坏,甚至升级一个次要版本可能需要数周的测试、验证和文档编写。在这个世界中,React 的平均次要版本升级都是一场磨难,而主要版本升级则是一场灾难。
将此与 Web 平台的向后兼容性保证相比,1996 年的 Space Jam 网站至今仍然可以正常工作。Web 组件融入了这个稳定性的故事,这对于没有奢侈每隔几年重写前端的任何公司都是一个巨大的优势。
当你使用 Web 组件时,connectedCallback 就是 connectedCallback,不会改变。而影子 DOM 的样式作用域,以及其中的所有微妙之处,也不会改变。任何你可以委托给浏览器的代码,都是你在多年内不必维护或验证的代码;你实际上已经把这个责任外包给了 Google、Apple 和 Mozilla。
企业行事缓慢、谨慎、风险回避,就像 Web 平台一样。难怪 Web 组件在企业界风靡一时。
Web 组件的缺点
所有 Web 组件的优点都应该与它们的弱点进行权衡。而 Web 组件也有它们的局限性:
服务器端渲染(SSR): 我认为在 Web 组件领域,这仍然不是一个解决的问题。当然,我们有声明性的 Shadow DOM,但那只是谜题的一部分。在服务器上渲染 Web 组件并没有标准,因此每个框架都会以略有不同的方式进行。Lit SSR仍然在“Lit Labs”中,这可能说明了一些问题。也许在未来,当你可以在服务器上渲染三种不同的 Web 组件框架,并且它们可以很好地组合和注水时,我会认为这个问题已经解决。但至少在未来几年内,我认为这还需要一些时间。
可访问性: 通过影子边界轻松跨越 ARIA 引用是不容易的,而对话框和焦点可能会很棘手。至少,如果你不想破坏可访问性,那么你必须从一开始就非常仔细地思考你的组件结构。尽管有很多正在进行的工作来解决这个问题,但我可以说在2023年,这方面确实还存在一些问题。
除此之外,还有一些锁定的问题(例如元框架
、打包工具
、测试运行器
)、IE11 的持续遗留问题(一些人可能因此受到终身创伤;他们最不想做的事情就是使用平台),以及框架疲劳(“我学会了 React
,它很好用,我不想学习其他东西”)。并非每个人都会被 Web 组件所吸引,而我对此感到可以接受。Web 是一个大帐篷,每个人都在用它做不同的事情;这正是使它如此令人惊奇的一部分。
总结
使用 Web 组件。或者不使用它们。或者在几年后再来检查一下,当功能和 Web 标准更加完善时。
我觉得 Web 组件很酷,但我理解并不是每个人都有相同的感觉。我不觉得自己需要四处传教,推动它们的采用。它们只是工具箱中的另一种工具;关键是发挥它们的优势,同时避免它们的缺陷。
我喜欢 Web 组件和 Web 标准的一点是,我可以将一堆乏味的问题外包给浏览器。如何组合组件?如何限定样式的作用范围?如何传递数据?谁在乎 - 只需使用浏览器提供的任何东西。这样,我就可以花更多时间解决真正关系到我的最终用户的问题,比如性能、可访问性、安全性等。
在 Web 开发中,我常常感觉自己在与与实际问题无关的附带复杂性
原文:https://nolanlawson.com/2023/08/23/use-web-components-for-what-theyre-good-at/