活动邀约 | 5月24日来交流AGI时代数据资产如何价值最大化? 了解详情
写点什么

术业有所专攻,Web 组件也是一样

作者 | Nolan Lawson

  • 2023-11-06
    北京
  • 本文字数:5351 字

    阅读完需:约 18 分钟

大小:2.50M时长:14:32
术业有所专攻,Web组件也是一样

前段时间,Dave Rupert 的文章《既然 Web 组件这么能打,我为什么不愿使用?》引起了不小的轰动。我自己使用 Web 组件也有几年时间了,所以想就这个话题掺和几句。

 

为了防止工程师大佬们说我有失偏颇,这里我先澄清一下:我觉得 Web 组件确实有利有弊,要不要用当然是个需要权衡的辩证过程。所以这里我们先分享几个 Web 组件发挥出色的案例,然后再讨论它们可能在哪些场景下表现不佳。

 

客户端渲染的叶组件

 

对我来说,这明显就是 Web 组件最能大展拳脚的应用场景了。假设我们在 DOM 树的叶分支上有一些组件,它们不需要在服务器端渲染,而且内部不<slot>任何内容。这方面示例包括:富文本编辑器、日历小部件、取色器等。

 

也就是说,我们已经直接回避了 Web 组件的那些天然弱项,比如服务器端渲染(SSR)、水合、slotting,甚至还有 Shadow DOM。如同大家没有使用框架,或者选择的框架直接支持 Web 组件,那只需要在模板或 JSX 当中添加<fancy-component>标签,即可达成预期效果。

 

例如,以我自己的 emoji-picker-element 为例。只需一行 HTML 即可将其导入:

 

<script type="module" href="https://cdn.jsdelivr.net/npm/emoji-picker-element@1/index.js"></script>
复制代码

 

再用一行就能使用:

 

<emoji-picker></emoji-picker>
复制代码

 

不涉及捆绑器、不涉及转译器,也不需要框架集成,直接复制粘贴即可。这就跟过去的 jQuery 插件一样。另外,我也见过在复杂 SPA 项目这么用的情况,Web 组件同样可以正常起效。

 

这也是 Web 组件在当初设计时的初衷,即应该能像使用内置 HTML 元素那样轻松使用 <fancy-element> 。

 

粘合代码,或者避免大规模重写


想象一下:我们有一套庞大的 React 代码库,它已经在业务系统中运行了一段时间。现在,团队想要迁移到 Svelte,那唯一的办法就是做整体重写了呗?包括为之前使用的所有第三方组件寻找相应的 Svelte 版本?

 

不少前端开发者确实是这么理解框架的,即从一种框架迁移至另一框架时会产生巨大的切换成本。但这其实是对 Web 组件的重大误解,并不存在换框架就得换组件这种事情。

 

更直白地讲,Web 组件的全部意义就是把我们从这种混乱当中解放出来。如果大家决定从 Vue 切换至 Lit,或者从 Angular 迁移到 Stencil,那么对所有组件做整体重写肯定要带来很多不必要的痛苦。

 

正确答案是,旧代码完全和新代码和谐共存。之后,我们利用 Web 组件的互操作性将二者粘合起来,即可回避大规模重写原有内容:

 

<old-component>  <new-component>  </new-component></old-component>
复制代码

 

Web 组件可以向下传递 props/attribute,并向上发送事件。(这正是 Web 组件的意义所在。)如果你的框架支持 Web 组件,那这一切都可以开箱即用。(如果不支持,也可以编写一点简单的胶水代码。)

 

我知道,有些朋友特别讨厌两套框架共存的情况,但我觉得这种判断大多是基于直觉、而非客观事实。公平地讲,如果大家的项目会使用元框架来进行 SSR/水合,那这种部分迁移在实际执行时确实可能难度很大。但 Web 组件最为擅长的,就是通过定义高级契约在客户端上把两个组件整合起来。

 

所以如果大家厌倦了每年都要重写整个 UI(或者老板不喜欢这样没完没了地折腾),那 Web 组件真心值得推荐。

 

设计系统和大企业需求


看看 Cassondra Robert 在 CSS Day 大会上的演讲,特别是他展示的一张演示文稿,就能感受到 Web 组件在重量级企业中的渗透程度:



除此之外,未列出的支持者还有甲骨文、SAP、ServiceNow 等等

 

大家可能已经注意到,很多大企业都在悄悄使用 Web 组件,特别是在各种内部设计系统和组件库当中。各位只要多在 webdev 社交媒体上逛逛,就会发现 Web 组件的普及度之惊人。另一个重大发现,就是根据某些量化指标,React 支持的页面加载占比约为 8%,而 Web 组件的使用率已经达到 20%。

 

问题在于,很多大公司并没有在社交媒体(Twitter/X、Reddit 等)上大肆宣扬自己在使用 Web 组件,或者指导大家怎么使用 Web 组件。另外,Twitter 上的很多技术大牛一直忙于介绍 React 各个小版本及生态系统中的新生内容。这种情况也有道理,毕竟大企业的讨论往往集中在内部,向外界传达的信息相对有限。而小公司(代理机构、初创企业和自由职业者)虽然体量不大,但在社交媒体上却更为活跃。如果即便 Web 组件在大厂当中更为活跃,外部视角下也未必显现得出来,至少他们不会在 Twitter 上反复强调。

 

那么,为什么大企业会如此热衷于 Web 组件呢?一方面,是因为 Web 组件在设计上能够在各种环境下顺利起效。大企业的前端往往由 React、Angular、Ember 和静态 HTML 共同编写而成,而且这一切还得跟公司的主题和品牌形象完全契合。前面提到的大规模重写对于小体量的初创公司可能是场有趣的演习,但在大厂层面上还是少搞为好。

 

再有,大厂的代码库需要面对更多用户、贯穿的时间尺度也更长久,所以必然受到各种不同技术决策的影响。在我看来,企业偏好 Web 组件的主要原因也正在于此:稳定性更好,寿命更长。

 

我们不妨设想各种常见的 React 代码库,包括对各种依赖项(React Router、Redux 还有 React 本体)的更新,是怎么耗费几个礼拜时间的重写来适应重大变更的。海勒姆法则认为当一个 API 有足够的用户的时候,在约定中做出的具体承诺将变得无所谓,系统中被观察到的所有行为都会被部分用户直接依赖。这话一点没错,海勒姆法则在企业规模上必然出现,而哪怕是一点点微小变化也可能引发蝴蝶效应、破坏数千个组件,甚至小版本变更也会带来几个礼拜的测试、验证和记录。事实证明,React 的每次小版本更新都是对业务系统的考验,而大版本升级更是堪称灾难。

 

相比之下,Web 平台领域也有出色兼容性的绝佳案例——1996 年上线的 Space Jam 网站至今仍在运行。这段稳定性传奇的背后正是 Web 组件的力量,这对没办法每隔几年就重写前端的公司来说当然是种巨大的优势。

 

在使用 Web 组件时, connectedCallback 就只是 connectedCallback,绝不会改变。无论我们把怎样的代码委托给浏览器,之后都可以历经多年不做维护或验证。具体来讲,我们实际上是把这份责任委托给了谷歌、苹果和 Mozilla。

 

大企业的风格就是缓慢、谨慎、厌恶风险——Web 平台也是一样。正因为如此,Web 组件才迅速席卷了整个企业世界。

 

Web 组件的短板

 

当然,Web 组件的一切优势背后,都有着与之对应的短板。下面来看 Web 组件做得不好的几个方面:

  • 服务器端渲染(SSR)。我觉得这个问题在 Web 组件领域长期没能得到解决。当然,我们已经有了声明式 Shadow DOM,但它本身也成了难题的一部分。由于服务器端的 Web 组件渲染缺少标准,所以每种框架的实践都略有不同。这一点从 Lit SSR 仍归于“Lit Labs”就能看出点端倪。也许未来,我们可以在服务器上渲染三种不同的 Web 组件框架,并把它们顺利对接并混合起来,到那时候这块短板才算真正被补齐。但我个人认为,这个目标至少还要几年时间才有可能达成。

  • 可及性。我们还是没法让 ARIA 引用轻松跨越阴影边界,对话框和焦点的处理也比较麻烦。总之,如果不想把可访问性搞得一团糟,那我们还是得从起步阶段就认真规划组件结构。这个问题的解决还有很长的路要走,而且 2023 年之内恐怕还不会有多少进展。

 

除此之外,锁定问题(例如元框架、捆绑程序、测试运行程序)、IE11 的持续遗留问题(这已经成了很多朋友的心理阴影,一看到 #useThePlatform 就浑身发抖),还有固守的排他性心态(我学的是 React,它很好用,所以我不想再学别的)也都客观存在。我只能说我自己对 Web 组件很满意,但并不是每个人都买它的账。但 Web 就是这样一个庞大的世界,不同的人用它做不 同的事,正是如此现实才让它展露出精彩纷呈的形态。

 

总结


总之,关于 Web 组件,大家想用就用、不想用就放下。或者再过上几年,等功能和 Web 标准更完善之后,咱们再回来试试。

 

我觉得 Web 组件很酷,但也理解为什么很多人对它毫不感冒。我不会为了推广 Web 组件而到处去布道,它们只是工具箱中平平淡淡的一个选项。如果它正好能帮你解决问题、自身短板又不会造成困扰,那就值得一试。

 

我最喜欢 Web 组件和 Web 标准的一点,就是可以把一大堆无聊的问题都托付给浏览器。怎么组合组件?如何确定样式范围?要怎样传递数据?管他呢,让浏览器去操心就好。如此一来,我就能把更多时间花在对最终用户真正重要的问题上,比如性能、可及性和安全性等等。

 

在 Web 开发当中,我经常觉得自己努力解决的根本就不是问题本身,而是问题附带而来的那些无关复杂性。我经常得在 npm 依赖项、状态管理调试,还有测试运行器为什么不能跟 linter 配合良好等麻烦事上浪费精力。其实解决这些问题也有爽感,很多朋友愿意亲自动手,我有时候也有这种感觉。但归根结底,这些纯粹是满足虚假成就感的无意义工作,毕竟最终用户根本就不关心你的捆绑器是否与 TypeScript 转译器保持同步。

 

现如今已经是 2023 年了,但使用 Web 组件还是会带来额外的复杂性,比如前文提到的 SSR 和可及性问题。任何一点处理不好,都会给最终用户带来感受得到的真实影响,所以大家要认真权衡这一切到底值不值得。

 

在我看来,选择 Web 组件仍然物有所值,但大家也可以有不同意见。“充分发挥 Web 的专长”这事虽然没啥吸引力,但却能切实帮我们解决实际问题。

 

网友评论


Jochen Kühner:喜欢你的组件,我试过,而且它确实能通过 NPM 在我的设计器里直接运行!(https://node-projects.github.io/web-component-designer-demo/index.html) 干得漂亮!

 

ED:对于声明式 Shadow DOM,我有一个疑问,不太明白你提到的问题。你提到 SSR(服务器端渲染)似乎还没有解决,具体指的是什么?实际上,服务器只需要发送页面结构,然后 Web 组件会在客户端自动完成更新(水合)。对我来说,重要的是客户端接收到的结构,不太关心这个操作在服务器上是如何执行的。如果你想了解更多关于我的观点,可以查看此链接:https://developer.chrome.com/en/articles/declarative-shadow-dom/

 

作者回复:确实,服务器端的 Web 组件输出应该有明确的标准格式,但实际渲染方法目前尚无通用标准。举例来说,对于需要事件调度的组件,服务器端如何处理呢?Node.js 缺乏 Event 对象和 dispatchEvent 方法。这使得服务器需要考虑是否要进行 polyfill,或者将事件视为类似于服务器上没有实际用途的 API,例如 getBoundingClientRect。

 

另外,考虑两个不同框架的组件在服务器端组合的情况。例如,当第一个框架遇到"other-component"标签时,服务器应该如何渲染它?难道要使用"document.createElement("other-component")"吗?然而,服务器端没有 document API,即使有,也难以确定哪个标签名称应该映射到哪个框架,或者应该使用哪种 API 方法(例如 Lit 中的 render,Stencil 中的 createRenderer 等)。

 

尽管 Web 组件社区已经开始讨论如何解决这些问题,但据我所知,不同框架之间尚未就这个问题达成一致的共识。

 

patricknelson:我认为这个话题非常有价值,其中最重要的观点是:我们可以通过 Web 组件的互操作性将不同部分结合起来,这种可组合性在大型企业、大规模项目和独立团队中都很常见,同时也作为迁移大型或老旧代码库的有效路径。

 

我目前在 eBay 的工作中积极应用 Web 组件。对我来说,Web 组件已成为不可或缺的重要工具。我正在将一个基于 PHP、jQuery 和 Sass 的老旧网站逐步迁移到 Svelte 上。在实现这个目标时,Web 组件发挥了关键作用,特别是轻量 DOM 渲染功能,这对满足各种需求(尤其是兼容 slot 和 Vite HMR)至关重要。为了弥合新旧代码之间的差距,我开发了一个名为 svelte-retag 的 NPM 包,它是 svelte-tag 的分支,用于简化过渡过程,避免立即进行大规模重写。这也为将来升级至 SvelteKit(与基于 PHP 的无头 CMS 配合使用)提供了重要基础。

 

Web 组件最引人注目的特性之一是其能够作为通用语言来规范化和序列化组件语言。这一点在 PHP 开发中非常有用,可以根据需要在任何位置生成和提交组件,然后轻松在客户端进行渲染。此外,Web 组件扩展了 SSR 的潜力,尤其是在使用轻量 DOM 时,甚至可以支持重度使用 PHP 的混合环境。虽然我尚未具体尝试,但我建议大家考虑尝试 enhance-ssr 和 webc,它们似乎为 Web 组件的 SSR 提供了更多选项,其中 webc 还提到了与浏览器原生 Shadow DOM 样式范围相关的特性。

 

另一个典型用例是在公司的主网站和招聘网站之间高效无缝地应用统一标头。这并不是依赖于 Svelte,而是一种封装方法,允许我们在基于 jQuery 和 Sass 的旧有布局和功能上发布基于 SSR 的标头,同时始终保持 Shadow DOM 的安全性,不受主页以外的外部干扰(反之亦然,毕竟我们不想在对方的代码中引入回归问题)。

 

尽管现在已经是 2023 年,但使用 Web 组件仍可能引入额外的复杂性,特别是在处理 SSR 和可访问性问题时。任何不当处理都可能对最终用户产生明显的影响,因此需要仔细权衡是否值得采用。

 

因此,考虑到这些因素,我目前仍然坚持使用轻量 DOM,因为它对我们来说带来了实际优势,特别是在支持旧代码方面。

 

作者回复:非常有道理!我认为实际上有大约 80%的所谓“Web 组件问题”其实都可以追溯到“Shadow DOM 问题”,因此,去除 Shadow DOM 可以避免许多可能的麻烦。然而,正如你提到的,轻量 DOM 中的“slots”也是一个重要特性,所以在放弃 Shadow DOM 的同时,我们也失去了<slot>,这确实令人遗憾。

 

参考链接:

https://daverupert.com/2023/07/why-not-webcomponents/

https://nolanlawson.com/2023/08/23/use-web-components-for-what-theyre-good-at/


相关阅读:

Web3当下,最佳投资就是投资自己

Web3的反思,不要抱怨

给Web3创业者的28个原则

和我一起学习Web3

2023-11-06 09:473845

评论

发布
暂无评论
发现更多内容

电动汽车安全概述

DevOps和数字孪生

电动汽车 汽车安全

嵌入式软件开发为什么需要DevOps?

DevOps和数字孪生

DevOps 嵌入式软件

大型集团公司如何打破“信息孤岛”问题?

优秀

打破信息孤岛 消除信息孤岛 信息孤岛

【墨菲安全实验室】WPS Office 存在代码执行漏洞

墨菲安全

网络安全 安全 漏洞 WPS Office

〔支付接入〕微信的 h5 支付和 jsapi 支付

极客飞兔

微信支付 支付 经验分享 H5支付 jsapi支付

百度、NVIDIA、Intel……各大厂商集结,共话文心与飞桨共享生态下的大模型训推部署创新实践计划

飞桨PaddlePaddle

人工智能 百度飞桨 硬件生态 WAVE SUMMIT

值得收藏!堪称神器的30个插件

Finovy Cloud

插件 渲染 建模 maya 3d建模

IoTDB 小白“踩坑”心得:入门安装部署篇

Apache IoTDB

【墨菲安全实验室】Apache Traffic Server Range 标头验证不当(CVE-2023-33934)

墨菲安全

Apache 网络安全 安全

【墨菲安全实验室】Zoom Desktop Client for Windows <5.14.5 权限升级漏洞(CVE-2023-36541)

墨菲安全

网络安全 安全 Zoom 漏洞 墨菲安全

【低代码预研】通过低代码平台开发应用程序

互联网工科生

软件开发 低代码 应用开发 JNPF

一文走进时序数据库性能测试工具 TSBS

KaiwuDB

性能测试 时序数据库 KaiwuDB

腾讯云大数据ES:结合AI大模型与向量检索的新一代云端检索分析引擎

腾讯云大数据

ES

【墨菲安全实验室】Microsoft Teams 远程代码执行漏洞 (CVE-2023-29330)

墨菲安全

安全 漏洞 网络安全、 Microsoft Teams

几个提高性能的小特性

这我可不懂

数据库 postgresql LOCALE

PP-ChatOCR:基于文心大模型的通用图像关键信息抽取利器,开发提效 50%!

飞桨PaddlePaddle

人工智能 百度飞桨

强劲实力闪耀榜单,智领云连续四年入选“中国大数据50强”

智领云科技

云原生大数据平台 智领云 云原生K8s大数据平台 大数据产业生态大会

聊聊低代码的本质,是应用开发的未来吗?

高端章鱼哥

低代码 应用开发 JNPF

确保数据一致性:单一可信数据源(SSOT)的概念与5个应用示例

龙智—DevSecOps解决方案

ssot single source

【墨菲安全实验室】Microsoft Exchange Server 远程代码执行漏洞(CVE-2023-38182)

墨菲安全

网络安全 安全 漏洞 Microsoft Exchange

如何在Confluence上设置到期日提醒?Confluence到期日提醒插件重要更新发布,优化表格提醒,增加屏蔽提醒功能

龙智—DevSecOps解决方案

confluence插件

龙智Atlassian认证专家、Perforce技术专家将于ACT汽车电子与软件技术周带来主题演讲,分享嵌入式开发中的最佳实践与工具链构建

龙智—DevSecOps解决方案

汽车电子 ACT汽车电子与软件技术周

【华秋干货铺】电源PCB设计汇总

华秋电子

详解低代码和无代码的区别

这我可不懂

低代码 无代码 应用开发 JNPF

甭提ChatGPT了,这个新的AI助手将永远改变人们的工作方式

互联网工科生

人工智能 AI 机器人

【墨菲安全实验室】Microsoft Office Visio 远程执行代码漏洞(CVE-2023-36865)

墨菲安全

网络安全 安全 漏洞 Microsoft Office Visio

14个前端开发者应该知道的实用网站

高端章鱼哥

前端 提高效率 前端开发工具

KeyShot 2023.2 Pro for mac(3D渲染和动画制作软件) v12.1.1.12激活版

mac

苹果mac Windows软件 KeyShot Pro 动画软件

巧用Maya轴心操作小技巧,工作事半功倍!

3DCAT实时渲染

maya制作技巧 3D软件教程

实现分布式事务:Java与MySQL的XA事务协调

树上有只程序猿

Java MySQL 数据库 分布式 XA

Dragonfly 发布 v2.1.0 版本!

SOFAStack

AI 算法 后端 基础设施 分发

术业有所专攻,Web组件也是一样_工程化_InfoQ精选文章