作者: 京東科技 牛志偉
一、讓人又愛又恨的Web Components
Web Components是一種用于構建可重用的Web元素的技術。它允許開發者創建自定義的HTML元素,這些元素可以在不同的Web應用程序中重復使用,并且具有自己的樣式、行為和功能。
Web Components并非一項新技術,而是一組持續演進的、由W3C標準化的組件化API。最早可以追溯到2011年左右,大約在2016年左右各個瀏覽器才實現了Custom Element V1版本。然而,在同一時期,諸如Vue和React等組件化框架已經開始主導前端開發生態。
盡管近幾年Web Components標準和技術都趨于成熟,但早期面臨的兼容性問題以及后來Vue和React等MVVM框架的崛起,導致Web Components領域一直處于低調狀態。接下來,我們將從Web Components的發展歷程、優勢以及開發中面臨的挑戰三個方面更深入地了解Web Components。
1、Web Components發展歷程
?2011年:Google發布了Chrome瀏覽器,并提出了“Shadow DOM”概念,這是Web Components的一個重要組成部分。
?2013年:谷歌工程師Alex Komoroske在Google I/O大會上首次提出了Web Components的概念,并推動了相關標準的制定。
?2014年:W3C發布了Web Components的規范草案,其中包括四個主要技術:Custom Elements、Shadow DOM、HTML Templates和HTML Imports。
?2015年:Web Components的規范逐漸得到瀏覽器廠商的支持,Chrome、Firefox、Safari等主流瀏覽器開始逐步實現相關功能。
?2018年:Web Components逐漸成為前端開發的主流技術之一,越來越多的開發者開始使用Web Components來構建可重用的組件。
?至今:Web Components技術不斷發展和完善,越來越多的框架和庫開始支持Web Components,使其在前端開發中發揮更大的作用。
2、Web Components有哪些優勢
?封裝性:Web Components 具有良好的封裝性,可以將頁面中的功能和樣式封裝在一個自定義元素內部,避免全局作用域的污染,提高了代碼的可維護性和可重用性。
?跨框架兼容:Web Components 是基于 Web 標準的技術,可以在任何支持 Custom Elements 和 Shadow DOM 的現代瀏覽器中使用,與各種前端框架和庫兼容性良好。
?標準化:Web Components 的規范由 W3C 組織制定,具有較高的標準化程度,有利于統一前端開發的規范和實踐,提高了代碼的可維護性和可移植性。
?性能優勢:通過使用 Shadow DOM 技術,Web Components 可以實現更好的性能優化,避免不必要的重繪和重排,提高頁面的渲染效率和用戶體驗。
目前,前端開發中有許多流行的框架可供選擇,如React、Vue、Angular、Solid、Svelte、Preact等。框架的選擇是一個復雜的決策過程。當框架版本升級時,項目可能需要面臨重構的問題。例如,從Vue2升級到Vue3可能需要付出較大的改造成本。如果不進行升級,就無法使用最新特性,甚至可能面臨框架舊版本不再維護的尷尬局面。在這種情況下,Web Components 的框架無關性可以在一定程度上改善這種局面。
就性能而言,以將 React 組件轉換為 Web Components 為例,可以優化執行過程,減少阻塞,提高頁面性能。在普通的 React 組件中,初次執行時需要一次性完成所有必須的節點邏輯,這些邏輯的執行會同步占用在 JavaScript 的主線程上。當頁面變得足夠復雜時,一些非核心邏輯可能會阻塞后面核心邏輯的執行。而通過使用 Web Components 優化 React 組件,執行過程會變得更簡潔。例如,注冊一個復雜的邏輯組件時,在 React 執行時只需執行一個 createElement 語句,創建組件只需要 1-2 微秒即可完成。真正的邏輯不會立即執行,而是等到“核心任務”執行完畢后再執行,甚至可以在合適的時機再執行,從而降低 Diff 成本。
3、使用Web Components開發的痛點
雖然Web Components具有許多令人喜歡的優點,但在實際開發中也存在一些棘手的問題。以下是幾個典型問題:
?原生開發難題:Web Components是一項原生技術,因此在組件編寫過程中需要回歸到原生開發。事件處理、狀態管理等方面都需要自行處理。盡管大多數框架都提供了對Web Components的封裝方案,但使用這些方案又需要引入相應框架的運行時,這導致脫離了框架無關性這一最大優勢。
?Form表單問題:在Shadow DOM中,包含、或
?樣式隔離問題:雖然樣式隔離有助于避免全局樣式污染的問題,但在某些場景下,如主題顏色等,仍需要將樣式同步到Web Components組件內部。目前可以通過CSS變量實現主題切換。此外,需要注意的是,slot插槽中的DOM元素樣式并未得到隔離。
針對這些問題,開發人員可能需要考慮采取一些額外的措施來解決挑戰,以確保Web Components在實際應用中能夠更加順暢地運行。
二、目前主流的Web Components組件方案
1、頭部案例
Twitter 2016 年開始將自己的嵌入式推文從 iframe 切換成 ShadowDOM,減少了內存消耗、加快了渲染速度,并批量渲染的時候保持絲滑。Upcoming Change to Embedded Tweet Display on Web?
Youtube
Youtube 作為 google 系的產品,很早就在全站用上了 Web Components,并且開源了自己播放器組件 GitHub - GoogleWebComponents/google-youtube: YouTube video playback web component此外 google 開源的 Web Components 還是很多的,Google Web Components · GitHub ,包括地圖、drive、日歷等等。
Github
Github 對 Web Components 的使用很早,具體可以看: How we use Web Components at GitHub | The GitHub Blog,2017 年 Custom Elements v1 版本在 chrome 和 safari 上相繼實現之后,Github 開始大范圍使。要知道 Github 2018 年才剛剛完全移除 jQuery:Removing jQuery from GitHub.com frontend | The GitHub Blog 這既得益于 Github 自身項目組件化的架構,也得益于 Web Components 本身與框架無關的特性非常識合作老項目升級。
Adobe Spectrum
?Adobe Spectrum 是由 Adobe 創建的設計系統,該站點是一個基于 Web Components 的 UI 框架產品。
2、方案對比
目前主流的 Web Components 組件方案有三種:
方案一:
?特點:以React和Vue為代表,通過將React或Vue組件包裝為Web Components組件的方式實現。
?優點:利用了本身框架的特性如生命周期、狀態管理等,易于開發者使用。
?缺點:需要引入本身框架的運行時,導致組件體積增加,同時喪失了框架無關性這一優勢。
方案二:
?特點:以Stencil和LitElement為代表,提供了專門的編譯器、工具鏈和語法糖來構建 Web Components。
?優點:相比第一種方案,引入本身框架的運行時可能更小,減少了體積。
?缺點:需要學習新的語法和工具,可能增加開發者的心智負擔。
方案三:
特點:以Svelte和Solid為代表,直接將組件編譯成原生 Web Components
優點:放棄了虛擬DOM,利用編譯或轉譯能力直接生成操作DOM的更新函數,性能優秀,接近原生DOM。另外Vue3中的Vapor模式,正是借鑒了這種模式,目前正在試驗階段。
三、與SolidJS結合的“化學反應”
1、SolidJS有何不同
SolidJS 是一個快速、靈活、可擴展的 JavaScript 庫,用于構建用戶界面。與其他前端框架相比,SolidJS 有一些獨特的特點和優勢:
?Reactivity System: SolidJS 使用基于數據變化的響應式系統,可以精確追蹤狀態的變化,并只更新發生變化的部分,從而提高性能。
?Fine-grained Reactivity: SolidJS 提供了細粒度的響應式更新,可以在組件級別、元素級別甚至屬性級別進行更新,避免不必要的重新渲染。
?No Virtual DOM: 與其他框架不同,SolidJS 不使用虛擬 DOM,而是直接編譯生成操作真實 DOM的函數,減少了 diff 算法的開銷,提高了性能。
?Hooks-based API: SolidJS 使用類似 React Hooks 的 API,使得組件邏輯更易于復用和組合
2、可以解決哪些問題
?直接在編譯階段生成原生Web Components,核心庫非常小巧,沒有額外的依賴,可以幫助減少項目的體積。
?提供響應式狀態管理、事件管理、生命周期等,解決原生開發的痛點。
?類React語法,上手容易,降低開發者心智負擔,轉換成Web Components十分流暢。
四、從0到1搭建 Aura Design Web Components組件庫
1、工程目錄設計
該項目采用了 Monorepo 設計,旨在統一管理各個子項目,避免開發階段頻繁發布/安裝 npm 包來同步代碼。具體內容包括:
?packages/eslint-config-aurai: 用于管理ESLint配置,集成了TypeScript和Prettier(用于JavaScript/TypeScript格式化)。
?packages/stylelint-config-aurai: 用于管理StyleLint配置,集成了stylelint-order(用于樣式屬性排序)和Prettier(用于樣式格式化)。
?packages/aura-design: 基于eslint-config-aurai和stylelint-config-aurai規范,使用Solid和Solid Element構建的Web Components元組件庫,包括按鈕、圖標、卡片、布局等基礎組件。
?packages/aura-design-pro: 與aura-design類似,但封裝了一些復雜組件,通常是依賴第三方庫的組件,例如支持Markdown渲染的富文本組件、視頻播放組件等。
?apps/aura-design-docs: 基于Storybook的組件文檔庫,支持查看代碼、組件預覽,并可實時預覽修改組件屬性。
?apps/react-starter、apps/vue-starter: 計劃用于驗證Web Components在React和Vue組件中的兼容性等問題。
?

?
?
2、部分細節展示
2.1、組件樣式編寫
Web Components組件中的樣式是內聯到每一個組件的Shadow DOM中,因此不能用常規的CSS Modules等方案。本項目中使用了大約4種不同的內聯樣式方案,以對應不同的應用場景:
?原子化CSS方案:UnoCSS致力于將所有樣式屬性細分為最小單元的CSS,以便實現最大程度的自由組合和復用。此外,UnoCSS還具有自動分析文件中使用的樣式的功能,只將實際使用的樣式打包,從而減小文件大小。
?

?
?
?CSS inline模式:利用Vite的功能,將外部樣式作為內聯模式引入,當需要自定義復雜樣式或語義化場景時,可能會使用此模式。
import styles from './Button.css?inline';
?CSS Template:CSS模板字符串類似于CSS-in-JS方案,通常用于根據prop變量動態控制樣式。盡管這種方法會增加一定的運行時處理邏輯,但可以有效減少CSS重復和文件大小。
const styles = css` :host { display: inline-block; } .box { height: ${props.size + 2}px; line-height: ${props.size + 2}px; position: relative; overflow: hidden; } .nums-chip { transition: transform 1.5s; transform: translate(0, -50%); overflow: hidden; } .number { font-size: ${props.size}px; line-height: ${props.size + 2}px; } `;
?CSS Link:使用link標簽引入外部樣式表,當組件樣式比較多、體積較大時,如果直接內嵌到組件內部,當有N個組件時,體積就會增大N倍(暫不考慮瀏覽器內置優化邏輯),而使用link標簽減少體積同時也可以利用上瀏覽器緩存的特性。
... return ( ???> ?link href={`https://cdn.bootcdn.net/ajax/libs/highlight.js/11.8.0/styles/atom-one-${props.theme}.min.css`} rel="stylesheet"??>?/link??> ?style??>{styles}?/style??> ?/??> ); ...
2.2、Svg圖標集成
Icon組件引入和注冊
import { defineCustomElements, registerIcon, Icon, } from '@aura-group/aura-design'; registerIcon('/iconfont.svg'); // 自定義svg圖標注冊,使用主項目根目錄的svg圖標文件,如果不注冊則使用默認圖標 defineCustomElements({ Icon }); // 注冊Web Components圖標組件
組件使用
?ar-icon name="download" size="20px" color="#4213de"??>?/ar-icon??>
2.3、組件打包
支持ES(按需加載)和UMD兩種范式,自動生成Typescript聲明文件:
package.json
{ "name": "@aura-group/aura-design", "version": "0.3.9", "description": "", "main": "dist/aura-design.umd.js", "module": "dist/aura-design.es.js", "typings": "dist/types/components/index.d.ts", "files": [ "dist" ], "type": "module", ... }
Vite相關配置
... build: { lib: { entry: 'src/components/index.ts', name: 'aura-design', fileName: (format) => `aura-design.${format}.js`, }, }, ...
3、基于Storybook的組件文檔
Storybook 是一個開源工具,用于開發和展示 React、Vue、Angular 等前端組件的交互式 UI 組件庫。通過 Storybook,開發人員可以在一個獨立的環境中編寫、展示和測試組件,而不必依賴于整個應用程序。這樣可以更快地開發和調試組件,同時也方便團隊成員之間的協作。
Storybook 提供了一個交互式的界面,開發人員可以在其中創建不同的“故事”(stories),每個故事對應一個組件的不同狀態或交互方式。通過 Storybook,開發人員可以輕松地查看和測試組件在不同狀態下的表現,從而更好地理解和調試組件的行為。
?

?
?
4、未來規劃
目前,我們的組件庫中包含了16個基礎組件和一些與AI Chat相關的組件。在 A-M 網站中,95% 的組件都源自 Aura Design 組件庫。未來,除了繼續封裝一些基礎組件外,我們將優先開發常規組件庫中缺失的比如AI應用的相關組件。隨著組件庫的逐步豐富和條件的成熟,我們會考慮將其開源。如果您有任何相關組件的封裝需求或希望成為項目的成員,請隨時與我聯系。
參考文獻
??ChatGPT?
??Web Components從技術解析到生態應用個人心得指北?
??2022 Web Components 趨勢解讀和展望?
??你不知道的 Web Components - 過去和未來?
?
審核編輯 黃宇
-
AI
+關注
關注
87文章
34223瀏覽量
275383
發布評論請先 登錄
評論