为什么我们使用 Web 组件

2025-05-27

为什么我们使用 Web 组件

由于 Rich Harris 发表了一篇关于为什么 [他] 不使用 Web 组件的精彩帖子,Web 组件再次在 Twitter 上流行起来

Rich 详细阐述了原始 Web 组件标准中的诸多技术(和非技术)问题,特别是自定义元素和 Shadow DOM API。Rich 详细阐述了 Web 组件本身的技术细节,但他得出的结论是,如果您对 Web 组件的本质及其使用方式的理解稍有改变,我们就会从根本上不同意他的观点。

注意:这并非有意攻击 Rich。我们是他作品的忠实粉丝,尤其是Rollup,它支撑着我们大量的开源项目,包括 Stencil,我们将在这里详细介绍。话虽如此,我们也是 Web Components 的主要用户,因此觉得有必要分享我们的观点!

实际情况是,如果你在 Web 组件之上添加一个工具或库,比如Stencil,几乎所有这些问题都会突然消失,Web 组件的强大功能就会真正显现出来。遗憾的是,关于 Web 组件与 React、Angular 或 Svelte 等第三方组件系统的争论似乎总是将第三方系统与不带工具的原始 API 进行比较,而涉及添加工具以获得相同结果的论点通常不被允许出现在这种争论中。

这很遗憾,因为它将焦点集中在原始 Web Component API 自身无法实现的功能上,而不是将这些 API 视为低级实用程序,只要添加一些辅助函数,它们就能转化为真正强大的工具。这本身也有点不公平,因为 React、Angular、Vue、Ember 等组件拥有工具和辅助库的优势,可以在 DOM 之上添加强大的功能,而这正是我们使用它们的初衷。如果 Web Component 的争论中不考虑工具,我们实际上就只能将其document.createElement与更高级别的组件系统进行比较,这显然是没有效率的。

考虑到这一点,我想就智能工具如何帮助您解决该帖子中列出的问题提出一些想法,而实际上没有 Rich 细节中的任何缺点,然后讨论 Web 组件解决的实际问题,而这些问题目前尚未被第三方工具或框架解决,为什么它们是相关且重要的,以及为什么今天许多开发人员强烈接受它们。

解决问题

让我们讨论一下 Rich 概述的一些问题以及如何通过工具或帮助库解决这些问题。

服务器端渲染和渐进增强。Web 组件本身不支持服务器端渲染,因此如果没有客户端的 JS,它们就无法工作,此外还存在其他相关问题。但是,Web 组件的 SSR 实际上可以通过预渲染 Web 组件并在客户端重新水化来实现,这甚至可以跨影子根工作!Stencil 就具备此功能,据我们了解,Salesforce 团队正在为其Lightning Web 组件使用类似的技术。这使得未启用 JS 的客户端和搜索引擎能够访问每个组件的完整渲染版本,而不仅仅是标签,从而避免了这个问题。这是一个实际操作的示例,还有另一个示例

JS 中无样式内容和 CSS 的闪烁。为了避免无样式内容闪烁 (FOUC),我们可以做一些事情。一种方法是仅在组件混合并设置样式后才将其设置为可见。例如,Stencil 会跟踪组件是否混合,并且仅在其父组件加载后才显示这些组件。这意味着当组件绘制时,它已经完全设置了样式,因此不会闪烁。另一种技术是使用可构造样式表 API,Stencil 会在可用时使用该 API。最后,我们可以在组件之间共享样式表信息。这意味着同一组件的多个实例不会在每个实例中都有重复的样式数据。有了这些技术,FOUC 将成为过去。

旧客户端需要 polyfill。Stencil会自动动态地找出哪些客户端需要 polyfill,并且仅在客户端需要时才加载它们。事​​实证明,这个数字实际上非常低,因为大多数现代浏览器(包括移动浏览器!)都完全支持 Web Component 作者使用的 API。这解决了他文章中的问题 #4。

控制是否渲染插入内容。在 DOM 中,元素会立即加载,这使得构建某些需要延迟加载内容的 UI 系统(例如路由器)变得棘手。控制元素是否加载的方法是首先不将其放入 DOM 中,或者在特定组件中管理如何渲染插入内容。使用StencilLitElement等顶层渲染助手可以提供帮助。在实践中,我们发现这不是什么大问题,并且已经使用基于 Stencil 的 Web 组件构建了一个受 React Router 启发的路由器,并在我们许多 Stencil Web 资产中都使用了该组件。

Props 和 Attributes 之间的混淆。Props 和 Attributes 在 DOM 中有着一段坎坷的历史,而 Web Components 又会使两者的处理变得更加复杂。然而,像 Stencil 这样的 Web Components 工具或像 LitElement 这样的库,可以轻松构建能够妥善处理组件 props 和属性变更的组件,而无需大量的样板代码。在其上添加像 TypeScript 这样的类型系统,可以轻松处理类型化的 props,并且在其他 Web Components 内部(或通过 JS)使用 Web Components,可以简化将非字符串数据传递给 props 的问题。

Rich 的 prop/attribute 管理和自定义元素样板代码示例确实看起来很糟糕,没有开发者会想写那样的组件代码。值得庆幸的是,如果你将 Web 组件 API 视为底层原语,就不必这么做。只需使用 Stencil、LitElement 或类似工具,你就能写出类似于你的框架的代码:

import { Component, Prop, h } from '@stencil/core';

@Component({
  tag: 'my-component'
})
export class MyComponent {
  @Prop() age: number = 0;

  render() {
    return (
      <div>I am {this.age} years old</div>
    );
  } 
}
Enter fullscreen mode Exit fullscreen mode

Rich 最后总结道,这些问题都已得到解决,Web 组件似乎正在逐渐与第三方组件模型相提并论。一方面,我们同意这一观点;另一方面,我们认为 Web 组件确实对现有框架做出了一些有意义的改进。

例如,Stencil 已证明,使用 Web Components 和智能工具可以帮助您获得一些最小、最快的应用程序。将更多工作推送到浏览器确实有一些好处!

Stencil 一捆大小

尽管如此,我们实际上认为围绕 Web 组件的技术讨论不如非技术方面的讨论有趣,并且相信通过更好地理解非技术方面,我们可以开始明白为什么 Web 组件如此有趣,以及为什么它们的采用一直在稳步增长。

希望我们也能证明 Rich 的结论“开发人员对 Web Component 标准漠不关心”其实根本不是事实!

解决组件分布和集成问题

如果 Web 组件仅仅是当今第三方组件模型的一个拙劣替代品,我们谁也不会在这里为它们辩护。然而,既然如此,我们就来聊聊 Web 组件实际解决的问题以及它未能解决的问题。

当然,Web Components 提供了一个原生的 Web 组件模型,但在前端 Web 开发中,组件模型种类繁多。每个使用流行前端框架的开发者都精通在他们选择的框架中创建组件。显然,仅仅提供一个原生的 Web Components 模型并不能解决普遍存在的问题,而这正是反对 Web Components 的一大论点。通常的论点是,第三方框架可以快速创新组件模型,而像 Web Components 这样的标准化框架总是“落后”,并且有可能巩固过时的方法。

那么,提供原生 Web 组件模型实际上解决了什么问题呢?它解决的最大问题是能够以高效的方式直接在浏览器中共享和使用开发人员创建的组件,而无需考虑应用程序技术。

这确实是团队面临的一个实际问题,但您的团队可能没有!您是否正在跨团队构建和使用各种现有和未来前端技术的组件?您的公司是否使用 React,但刚刚收购了一家使用 Angular 的公司?您是否需要将设计系统集成到传统的服务器渲染系统中,例如 JSP/ASP.NET/PHP 等?您是否需要将现代 JavaScript 驱动的组件添加到没有传统“框架”的旧式 Web 应用或 CMS 中?您是否正在构建一个像 Ionic Framework 这样的 UI 框架,该框架需要兼容所有前端技术?

这些问题正是 Web Components 独有的解决之道,对于面临这些问题的团队来说,没有任何其他方法能够真正解决这些问题。事实上,如果你正在构建一个可复用的 UI 库,却不使用 Web Components,那么从长远来看,你将面临一个充满挑战、可寻址市场极其有限的世界,相信我们!

今天谁在使用 Web 组件?

Web 组件争论中经常出现的问题之一是缺乏 Web 组件使用的生产示例。

我们认为有几个例子可以证明 Web 组件能够独特地解决这些问题。

让我们从Ionic Framework开始。Ionic Framework 最初是 AngularJS 和 Angular 的移动 UI 库,两年前经过彻底重写,转变为可在任何基于 Web 的前端环境中工作的组件模型,我们将其称为 Ionic 4。我们受到商业指标的推动,例如扩大我们的社区和潜在市场,以及技术动机,例如不必为未来的框架再次重写 Ionic,并显着提高加载和渲染性能。我可以自信地说,Ionic Framework 4 是最成功的基于 Web 组件的设计系统 /UI 框架,并且 Web 组件现在已存在于数千个应用商店应用中,并且每年有近 400 万个新的 Ionic Framework 项目被创建。这是 Web 组件的重要使用情况!最重要的是,Ionic Framework 4 开发人员可能甚至不知道他们正在使用 Web 组件,因为它们与 Angular 以及我们即将推出的 React 和 Vue 支持无缝集成。

除了 Ionic 之外,如今还有许多初创公司和大型企业正在使用 Web Components 进行开发。在初创公司方面,热门健身应用 Sworkit 最近推出了基于 Ionic Framework 4 的全新 PWA 和原生应用,并在网页端和应用商店中均使用了 Web Components。

你很难找到比 Salesforce 更大的例子,它最近将其 Lightning 组件移至 Web 组件,并且一直是基于 Web 组件的设计系统的先驱。

另一个例子是上市公司 Upwork 最近在其主页上发布了使用 Stencil 构建的 Web 组件。

各国政府也纷纷加入!密歇根州最近推出了一套基于 Web Components 和 Stencil 的设计系统。

最后,Stencil 正在日益成为 Ionic 业务的重要组成部分。我们最近签约了几家知名企业客户,他们共同的感受是,Stencil 和 Web Components 帮助他们解决了在众多资产和团队中遇到的组件分发和创建问题,而这些资产和团队通常没有一套固定的前端技术。我们希望将来能够分享更多类似的案例。

竞争愿景

Web 组件生态系统拥有多样化的参与者,他们对 Web 组件可以做什么和应该做什么有不同的长期愿景。

有些人认为 Web 组件应该取代第三方应用框架。另一些人则认为 Web 组件实际上更适合用于叶子/样式/设计节点,不应该介入应用组件系统。此外,还有一大批应用框架开发者根本不懂 Web 组件的意义,或者认为 Web 组件是对前端创新的侮辱。

我们处于中间位置,并不代表这个领域的所有人。我们的长期愿景是,应用开发团队可以继续使用他们选择的框架,并希望这些框架能够变得更好、更小、更高效,并且对定位和使用 Web 组件的支持也越来越好(随着公司继续采用 Web 组件作为共享设计系统,大型团队将越来越多地使用 Web 组件)。

与此同时,我们相信 Web Components 的杀手级应用正在解决这些组件分发和设计系统问题。我们也认为 90% 的市场并没有这些问题,并且认为目前关于 Web Components 优缺点的争论有些徒劳无功。

奇怪的是,从商业角度来看,这个市场的形态确实很吸引人。大规模设计系统是大型团队和公司独有的问题,这意味着这里存在着天然强大的企业业务!

结论

Web 组件是一项颇具争议的技术,支持者和反对者不一。我们认同该标准仍有改进空间,并希望 Rich 的文章以及其他作者能够帮助浏览器厂商改进该标准。

我也明白,我们的许多反驳意见都不会让那些坚持认为 Web 组件只有在无需任何额外工具即可支持框架功能时才算准备就绪的开发人员满意。

话虽如此,我们一直认为 Web 组件是一种底层技术,当它们与 Stencil 或 LitElement 等合适的工具和库结合使用时,其强大的功能令人惊叹。对于需要所有功能的团队,我们坚信 Stencil 是最佳解决方案,它不仅能满足您的所有需求,还能提供一些您目前所选框架中可能没有的强大功能,包括最小的代码包、SSR/预渲染、最佳的 PWA 性能和高级延迟加载。对于团队而言,Stencil 可以从您的组件自动生成文档,运行可视化 UI 回归测试,并为 Angular、React 和 Vue 生成原生包装器。您可以在我们的1.0 版本公告文章中了解更多信息。

Web 组件解决了一系列非常特殊的问题,而许多团队(尤其是规模较小的团队)并没有遇到过这些问题。对于这些团队来说,创建 Web 组件与其应用框架的组件模型相比,带来的价值微乎其微。然而,我们预计,随着 UI 库和设计系统开发者逐渐接受这项标准,并接受它比其他任何前端技术都能更好地解决特定问题的能力,这些团队将越来越多地使用 Web 组件。

对于确实存在这些问题的团队来说,没有其他技术能够充分解决这些问题,因为没有其他技术在浏览器中直接原生支持。如今,这些问题主要出现在规模较大的公司中,这些公司对特定前端技术的使用规则不那么严格,或者团队瞄准更广泛的 Web 开发生态系统,而这些生态系统中还没有哪一种前端技术真正占据主导地位(甚至 React 也没有)。

如果您是其中之一,我们希望您能认真研究一下 Web Components 的功能,只需提供一点帮助即可。我们确信,Web Components 是 Ionic 作为一家公司以及开源 UI 设计系统的创造者所经历的最棒的事情。如果您遇到本文提到的任何问题,我们希望您能够尝试一下!

文章来源:https://dev.to/ionic/why-we-use-web-components-2c1i
PREV
gitignore.io 很棒!
NEXT
识别冒名顶替综合症并在它搞砸你的编码面试之前解决它你所知道的一切不断膨胀的宇宙其他人都知道这是一个焦点问题