这篇文章会重点关注 Web Components 在生态、行业应用方面的现状,也会涉及一些 Web Components 之外的技术,为你做 Web Components 技术应用选型提供一些参考。关于具体 API 介绍示例代码,官方文档很全,本文不会提太多。
Web Components 是一套技术,让我们可以创建封装功能的定制元素,在任何地方重用且不产生冲突影响。 Web Components 现阶段主要包括三部分,在社区里也经常被提到:
其实还有两个在 Web Components 历史上出现但逐渐不再被提到的名词:
注意 Web Components 自己本身不是一个规范,二是一套整体技术,他包含的三部分内容是独立规范。 比如 Shadow DOM ,本质是一组 JS API,其实浏览器一直依赖都用它来封装一些元素的内部结构。比如 Element.attachShadow()
也许你会问既然已经存在,ShadowDOM 的推进还有什么难度?难度在于用于Web Components 的 ShadowDOM 需要把内部机制通过合适的 API 暴露给开发者用,同时要考虑相关的兼容问题。
同样的,可以只用 Custom Elements 来扩展 HTML。 只用 Template 也可以动态生成 DOM。
但依照这些规范结合在一起用,用Shodwo dom 结合 HTML Template、Slot 操控 Custom Elements 中的子元素应该放到 ShadowTree 的什么位置,我们就能够构建独立的、可重用的组件,并像内置的 HTML Elements 一样无缝集成到现有应用。
如果想了解 Web Components 的历史和更多技术细节可以转到 👉 《你不知道的Web Components - 过去和未来》
原生支持,无三方依赖
使用简单,适合很多特殊场景,比如架构升级、跨框架融合等
自定义组件名语义性好
性能优势。
组件隔离,ShadowDOM带来的天然隔离。
技术栈无关,无论跟什么后端语言都能方便结合。
在商业场景下更小的迭代迁移成本,利于复用和分享,
主要有几类方向:
Twitter 2016 年开始将自己的嵌入式推文 从 iframe 切换成 ShadowDOM,减少了内存消耗、加快了渲染速度,并批量渲染的时候保持丝滑。Upcoming Change to Embedded Tweet Display on Web
Youtube 作为 google 系的产品,很早就在全站用上了 Web Cmponents,并且开源了自己播放器组件 GitHub - GoogleWebComponents/google-youtube: YouTube video playback web component 此外 google 开源的 Web Components 还是很多的,Google Web Components · GitHub ,包括地图、drive、日历等等。
EA 的游戏工作室分布在全球各地,为了保证不同团队和工作室的设计开发体验统一,EA 基于 Web Components 构建了自己的 Network Design System,同时也支持这自己的 UIaaS。
github 对 Web Components 的使用很早,具体可以看: How we use Web Components at GitHub | The GitHub Blog 2014 年 Custom Elements v0 specification 出现的时候 github 就开始关注:Search · topic:web-components org:github · GitHub,并且开源了其中一系列 Web Components GitHub - github/github-elements: GitHub’s Web Component collection. 2017 年 Custom Elements v1 版本在 chrome 和 safari 上相继实现之后,github 开始大范围使用
要知道 github 2018 年才刚刚完全移除 jquery Removing jQuery from GitHub.com frontend | The GitHub Blog 这既得益于 github 自身项目组件化的架构,也 Web Components 本身与框架无关的特性非常识合作老项目升级。
github 还开源了 用于开发Web Components 的库 Catalyst:GitHub - github/catalyst: Catalyst is a set of patterns and techniques for developing components within a complex application.
而他的思路借鉴了 Stimulus 和 LitElement。
同时 github 还开源了一个 View Component 框架用来在 ruby on rails 里面构建同构应用 GitHub - github/view_component: A framework for building reusable, testable & encapsulated view components in Ruby on Rails.
SalesForce 作为一家 ToB 服务的公司,面对各种不同技术栈的客户,选择 Web Components 原因有两点,一是需要一套统一的通用组件面向所有客户,二是在很多特定领域,很多客户很难对他们的传统技术体系做大规模升级,而引入 Web Components 可以避免这类技术改造风险。
他们开源了自己的 Web Components 组件库 Component Library,并提供一整套基于 的企业级研发工具 GitHub - salesforce/lwc: LWC - A Blazing Fast, Enterprise-Grade Web Components Foundation 除了通过 LWC,让客户可以在自己的环境中基于组件库配置、开发、部署应用,SalesForce 还开放了自己的 SalesForce 工作平台 ,平台为所有客户提供一站式配置、部署和升级的能力。
Oracle 在 2017 年开始在自己的 GitHub - oracle/oraclejet: Oracle JET is a modular JavaScript Extension Toolkit for developers working on client-side applications. 构建工具中增加了对 CustomElement 的支持,在此之前是用的是 jQueryUI。Oracle 对 WebComponents 对态度其实很值得 ToB 同行学习,他并没有刻意想拜托 jQuery,而是让 WebComponents 与现有的 jQuery、Knockout 并行使用,只在新功能上推进 WebComponents ,保持老项目稳定,在历史遗留和新技术之间保持了合理的平衡。 而在 jet 的生态方面,他们也在持续建设 Web Component 驱动的共享组件中心 Building the future of Oracle JET Ecosystem | by João Tiago | Digital Transformation Research Group | Medium
Web Components 的社区说起来有几种阵营,也跟早期 Web Components 发展曲折有关,一些基础库在某个时间点提出,随后诞生出一系列周边生态库。主要包括:
这应该还是大家比较熟悉的,Google 从 2013 年开始一直在持续推进的基于 Web Components 封装的类库,同时还开放了基于 Polymer 开发的组件集合 PolymerElements · GitHub 和开发周边。 2015 年 Google 正式发布 Polymer 1.0 ,注意时间点,当时还是Custom Elements v0 版标准 2017年Custom Elements v1 版标准在各大浏览器落地,Polymer 发布了 2.0,并且不再封装 Custom Elements API,不再默认使用shadowDOM、目标兼容各种框架,开始变成轻量级类库。
但个人觉得总体上相比与彼时流行的其他框架 Polymer 还是不温不火,Google 似乎也有同感、随着 Polymer 的轻量化升级,于是在 2018 年又发布了更现代化的 lit GitHub - lit/lit: Lit is a simple library for building fast, lightweight web components. 包括 lit-html 模板渲染库 lit/packages/lit-html at main · lit/lit · GitHub 和基于 lit-html 的 lit-element lit/packages/lit-element at main · lit/lit · GitHub 创建 Web Component 的 base class 。 Lit-html 基于 ES 的模板自变量和 template 标签,用注释节点去动态填充,没有JSX 转换虚拟 dom的过程,把大部分模板创建渲染的事都交给浏览器去做,提供了轻量的 api 让我们可以在 JS 中写 HTML-Templates。 Lit-Element 的 Reactive properties 、Scoped styles 等面向现代化 JS 语法的特点让他现在很受欢迎。 Google 推荐新用户使用 lit,但也将 Polymer 推到了 3.0 版本,放弃了 HTML Imports 转向 JS modules,并且支持 Polymer 跟 lit 混用,目前持续又维护和支持,Slack Channel 上一直很活跃。
除了 Google 自己, 微软的 PWA stater GitHub - pwa-builder/pwa-starter: Welcome to the PWABuilder pwa-starter! Looking to build a new Progressive Web App and not sure where to get started? This is what you are looking for!,选择 lit 框架和 封装的 Web Components 作为基础库。 Adobe 基于 LitElement 封装并开放了 Spectrum Web Components Sap 基于 Lit-html 封装并开源了 ui5-webcomponents/02-custom-UI5-Web-Components.md at master · SAP/ui5-webcomponents · GitHub Red hat GitHub - 1-Platform/op-components: One platform component library. 等众多公司使用了 lit 开发自己的组件库或平台。
另一个类库 GitHub - skatejs/skatejs: Effortless custom elements powered by modern view libraries. 也是基于 lit-html 的。
Stencil: 2019 年6月正式发布第一版,官方定义是一个Web Component 编译器, Ionic 团队开发,把现在流行的虚拟 dom、异步渲染、响应式、JSX 等概念都做了支持,并且自己只是一个构建时工具。用 Stencil 开发的框架可以独立运行、也可以运行在主流框架,毕竟是 ionic 团队的产物。Stencil 可以开发 ionic 框架需要的组件库,其实也就成了整个 ionic 体系的核心之一,Ionic 基于 Stencil 也开源了他们的跨三端、支持框架的组件研发工具 UI Toolkit GitHub - ionic-team/ionic-framework: A powerful cross-platform UI toolkit for building native-quality iOS, Android, and Progressive Web Apps with HTML, CSS, and JavaScript. 所以我理解他非常适合用来探索如何把 Web Components 跟 其他框架、应用混合,甚至是构建跨框架的组件系统。
FAST 微软 2020 年发布的标准化解决方案,可以用来创建组件和设计系统。组件核心是基于 Web Components 做到 框架无关,并把它成为可以通用适配的 adaptive UI 。 由于 Fast 出自微软 Edge 团队,Edge 也在 settings 页面使用了 Fast 。而出自微软 office 团队的 Fluent 组件库起初定位是 React 组件库,随后也支持了 Web Components fluentui/packages/web-components at master · microsoft/fluentui · GitHub 。 Fast 在跟其他框架集成方面也做得比较好,包括三大框架甚至,以及微软自己的 Blazor,近两年尤其对于 ASP.net 等开发路线的用户有很好的吸引力。
现有的浏览器 devetools 还没发完全支持 Web Components 的研发,于是有了Web Component DevTools,目前支持了 Chrome 和 FireFox 的插件,可以帮助监听、过滤展示 Custom Elements,修改属性、监听事件、调用函数等等。 这套工具其实也是 Lit 开发团队做的,在 slack 上同样能看到相关的讨论进度
Eslint 和 prettier 都已经有了相应的支持, @open-wc/eslint-config - npm 则集成一些默认的最佳配置。
在lint 工具的基础上, VSCode/IDEA/Atom 等 IDE 也都支持了 Web Components 相关的语法高亮和插件,可以在各自插件市场找到。
2022 年几乎所有的主流框架都支持了 Web Components Custom Elements Everywhere
在这么多框架类库支持的情况下,我们可以看下开发实现 Web Components 的方式有哪几种类型:
最直接的方式是基于基础库开发,目前支持 Web Components 的基础库主要分位一下几种类型:
老牌流行框架由于发展较早,对 Web Components 的支持主要一运行时封装为主:
新兴前端框架/库很多支持了构建时编译:
有实验统计了用这些方式实现 30 个 Web Components 的体积尺寸上的情况:
可以看到基于原生或基础库开发的方式体积最小,而运行时封装的方式、由于框架/库自身运行时存在,体积最大。 而另一个50个组件的渲染性能统计则可以看到,构建时编译 Web Components 和基于基础库开发并没有太大差别,甚至有的逼近原生: 运行时封装的方式思路在各方面表现都不行,但它确有最小的研发改造成本。所以对于具体的实现方式可以总结下:
实现 Web Components 的方式 | 渲染性能 | 资源体积 | 研发/改造成本 |
---|---|---|---|
运行时封装 | A | B框架自身运行时过大 | A++ 无需对现有组件改造 |
构建时编译 | A++ 接近原生 | A+ 与原生略有差距,但可以接受 | A 需要通过工具链转换,有开发工具链的成本 |
基于原生/基础库开发 | A++ | A++ | A 现有组件只能重写 |
现阶段的 Safari 和 Chrome 已经都原生支持了 Web Components 的规范标准。Firefox,Edge 和 IE11 在 Polyfill 的支持下也都能很好的支持 Web Components。
在 Chromium 中,有实验表示 ShadowDOM 相比常规 DOM 节点创建的开销大约是 3 倍。 原因在于 Shdaow Host 比普通 DOM 节点携带更多的状态信息,包括 Shadow Tree 的 DocumentFragment、CSS Scope 信息等,因此解析和附加 Shdaow Host 所需的时间大约是解析添加常规 DOM 节点的三倍。 这个测试使用的还是实验阶段的 declarative Shadow DOM,所以纯命令式 Shadow DOM 的开销会更高,因为需要解析和执行 Javascript 来调用 attachShadow。
我理解这并不表示使用 Web Components 的页面会慢三倍 ,页面的加载时间受到网络、样式和布局、资源规模、框架等多方面影响。在实践中如果跟 React 组件相比, CustomElement 的 upgrade 机制和 HTML templates,可以让组件在加载时不使用,而在运行时实例化,而普通的 React 组件需要走完所有必要节点逻辑, 同时有实验 Web Components Basics and Performance Benefits | by Sheeshpaul Kamboj | Medium 测试 React 会消耗更多(7倍)的 CPU 成本用来做 JSX 解析、CSS-in-JS 转换、协调调度、虚拟 DOM比较,而 Web Components 不产生框架带来的附加成本,Web Components 的真实渲染性能是更好的。
Chorme 的数据显示, 目前有 17% 的网站至少使用过一个 CustomElements,而这个数据在2019 年之前几乎为 0。 同时 Web Componnents 在 PC 和移动端上也没有偏好差异, 两端的增长速度都很快:
如果想了解 Web Components 的历史和更多技术细节可以转到 👉 《你不知道的Web Components - 过去和未来》