為什麼 Shadcn UI 是 2023 年前端最熱門的開源專案?

2023 年在 GitHub 獲得最多星星 (39.5K) 的專案

Leo Chiu
手寫筆記

--

前言

shadcn/ui 是 2023 年在 GitHub 上星星數量成長最多的專案,總共獲得了 39.5k 的星星數,而且在 2023 年 1 月的時候才被發佈到 GitHub 上面,在 2024 年 3 月已經成長到 50K 星星數,這個成長速度非常可怕,究竟是什麼魔力讓大家都願意貢獻給它一顆星星呢?

最近在做個人專案的時候正在思考技術選型,考慮了一些熱門的 UI library,包括 MUIAnt DesignChakra 等等,然後就找到了這個 2023 年最熱門的專案。一開始在看 Shadcn UI 元件的樣式時並沒有覺得特別的令人驚艷,提供的元件也跟其他 UI library 沒什麼不同,所以很好奇為什麼這個專案為什麼會是 2023 年星星成長數量最多的專案呢?

在這篇文章中會簡介 Shadcn UI 這個專案,並且會整理的一些在選擇 Shadcn UI 大家也許都會想到的問題,提供給大家做技術選型的參考。

Shadcn UI 簡介

首先要先提到一很重要的一點:

Shadcn UI 不是 component library

Shadcn UI 與常見的 MUI、Ant Design 和 Chakra 等等的 component library 不一樣,它並不是一個 component libary,那它是什麼呢?

實際上它是彙集了各種元件的一個專案,讓你選擇需要的元件,並且複製貼上到你的專案中。而且他沒有自己的 npm package,這意味著你不會在 pacakge.json 中看到 Shadcn UI。

https://ui.shadcn.com/docs/components/card

看到這邊你一定又會想,只是複製貼上有什麼特別的,跟網路上常見提供範例程式的網站有什麼不同?

Shadcn UI 的底層是 Radix UI

Radix UI 是一個 headless component library,這表示它的元件沒有任何的樣式,它提供了可以客製化樣式的方式,讓我們自定義元件的樣式。

https://www.radix-ui.com/

此外,Radix UI 的所有元件都符合 WAI-ARIA 的要求,如果你需要建立具有 accessibility 的專案,Radix UI 無疑是一個好的選擇。

另一個我覺得最神奇的一點,是 Radix UI 的所有元件都可以單獨下載,你不用在一開始就安裝整包的 component library,而是安裝需要的元件到你的專案中即可:

npm install @radix-ui/react-dialog
npm install @radix-ui/react-dropdown-menu
npm install @radix-ui/react-tooltip

如果你不需要 Shadcn UI 提供的樣式,也可以自己使用 Radix UI 封裝成所需的元件庫。

Shadcn UI 使用 Tailwind CSS 封裝 Radix UI

Tailwind CSS 無疑是近年來大家最常聽到實現了 atomic css 的 CSS 框架,而 Shadcn UI 則是用了 Tailwind CSS 封裝了 Radix UI 的元件,你從 Shadcn UI 上複製的元件都有 Tailwind CSS 的蹤跡。

除了 Tailwind CSS 之外,另一個值得一提的是 class-variance-authority(cva)這個套件,這個套件也會在 Shadcn UI 中經常看到,它讓元件有了 variant的功能。

https://ui.shadcn.com/docs/components/button

使用 Shadcn CLI 下載元件到你的專案

Shadcn UI 的主要功能就是讓你複製元件的原始碼,它提供了 CLI 跟手動複製兩種方式,使用 CLI 便可以很快速的將元件新增到你的專案中:

npx shadcn-ui@latest add alert

技術選型的問題

將 Shadcn UI 的元件複製下來,不就需要自己維護嗎?

在看到這個專案的時候,很多人都會有這個問題,如果遇到 bug 的時候怎麼辦?這的問題不太準確,有兩點是大家需要思考的。

首先,不論是 Shadcn UI、MUI 或 Ant Design,只要修改了其元件的樣式都需要我們自己維護,所以維護這個問題是必然的,除非你不需要客製化樣式。

其二,Shadcn UI 的底層是 Radix UI,元件的功能是實作在 Radix 上面,跟 Shadcn UI 沒有關係,所以當發生了 bug 或是需要新功能時,則是要去看 Radix UI 是否有更新,而不是 Shadcn UI。

所以這個問題的答案是「對的,你要自己維護,但是只需要維護樣式的部分」。

Shadcn UI 的專案蠻多 issue 怎麼辦?

貌似 Shadcn 作者在加入 Vercel 之後比較少在更新,所以 issue 現在蠻多的,而且更新速度並不一定會如大家預期。

但如上個問題所述,Shadcn UI 裡面只有樣式,元件的功能是 Radix UI 提供的,所以當發生問題時要看的是 Radix UI 的狀況,而並非 Shadcn UI。除非你需要的是 Shadcn UI 的 issue 提到的某個新的功能或是樣式,但屆時也許也是用複製貼上的方式去更新 codebase 中的元件。

p.s. Shadcn UI 的作者 Shadcn 正在 Vercel 製作一個名叫 v0 的專案,這是 v0 的簡介「Generate UI from simple text prompts and images.」。

什麼時候不要使用 Shadcn UI?

我想這個是大家都想問的一個問題,可以快速總結為幾點:

  • 你不想要自己維護所有的樣式:因為 Radix UI 的元件都沒有樣式,這意味著所有的元件樣式都得自己建構跟維護,這是個雙面刃,你擁有元件樣式完整的控制權,但就得花費更多心力去維護。如果你依賴了 Ant Design,而按鈕只改了 border-radius,其他樣式則是由 Antd 提供,不用花費很多心力去維護樣式,只需要擔心升級的時候會不會跑版,或是聖誕節會不會突然跑出聖誕彩蛋
  • Radix UI 無法滿足你的需求:Radix UI 畢竟還是比較小眾的元件庫,其星星數只有 3.4K 而已,比起 Shadcn UI 少了 10 幾倍,如果遇到 bug 或是需要新功能時,能得到的社群資源相當有限
  • 不想自己維護元件的文件:如果在會持續迭代的專案中使用 Shadcn UI 還有一個明顯的缺點是「文件必須隨著元件持續更新」,當我們使用較完整的元件庫像是 Ant Design、MUI 等等,其元件的用法更新時會有官方負責維護文件,但我們使用 Shadcn UI 代表著多了一個可能會需要持續更新元件的成本。

Shadcn UI 跟 Ant Design 該怎麼選

Ant Design 的優點:

  • 涵蓋了非常廣泛的使用者行為
  • form 系統很完善
  • 提供的元件非常多樣化
  • 阿里巴巴旗下的套件,對於維護性無庸置疑

Ant Design 的缺點:

  • 前幾年發生了聖誕彩蛋事件 🥚
  • 功能多所以相對來說體積較為肥大
  • 大版號經常會有 breaking change

Shadcn UI 的優點:

  • theme 的系統很完善,而且簡單
  • 擁有高度客製化的彈性,因為你擁有了原始碼
  • 較為輕量,你不用把所有的套件都安裝到你的專案下
  • 符合 A11y 的規範

Shadcn UI 的缺點:

  • 未來的更新可能會比較辛苦一點,因為你擁有了所有的原始碼,更新元件的同時可能需要同時維護文件
  • 元件較為簡單,通常都需要自己再客製化元件
  • 對於 table 等等有大量資料互動的元件較為弱勢

可以簡單總結為,如果 Radix 提供的元件功能可以符合需求,Shadcn UI 也能符合你的需求,不需要安裝較為重量的 Ant Design。但是相對起來 Shadcn UI 需要維護的成本有可能會高一些,因為你需要維護所有的樣式及文件。

簡單的應用或是不會需要持續迭代的專案也許 Shadcn UI 滿足你的需求,而且使用上也很簡單;而 Ant Design 的功能很完善,對於如果是需要大型 form 或是 table 的應用,還有許多額外的功能,在複雜的應用中選擇 Ant Design 是個不錯的選擇。

其他我在使用 Shadcn UI 遇到的問題

form 元件的結構有點怪

這是 Shadcn UI 提供的 form 程式碼片段,可以看到 form 宣告了兩次,這就有點讓我覺得 DX 有點怪怪的,為什麼不是一個 form 呢?

https://ui.shadcn.com/docs/components/form

我覺得這邊的封裝有點誤導,實際上 Shadcn 的 <Form> 是封裝 react-hook-form<FormProvider>,兩個一樣的名字讓人第一時間會覺得這邊很怪。

如果去看 Shadcn UI 的 form 原始碼,會發現它並沒有使用 Radix UI 的 form,因為 Radix UI 的 form 使用原生瀏覽器的 form,在 React 中做表單驗證可能會用到各式各樣不同的功能,所以 Shadcn UI 反而使用 react-hook-form 自己封裝。

Shadcn UI 的 DatePicker 並非由 Radix UI 提供

因為 Radix UI 沒有 DatePicker 這個元件,所以 Shadcn UI 中使用的是 React DayPicker 這個套件,其提供的功能比較少一點,沒有選擇月份或是年份的功能,所以如果你需要更多的功能則需要另外找一個套件才行。

在 ReactDayPicker 的官方 GitHub 中也有提到 MonthPicker 這個功能已經超出該套件的範疇,所以如果需要該功能可以自行製作。

另一個點是 React DayPicker 依賴的是 date-fns,並不能替換底層處理 date 的套件,如果想要使用 dayjs 的話得考慮其他的套件。

總結

看完這篇文章你應該可以了解 Shadcn UI 的有哪些特性,我們知道 Shadcn UI 跟許多的 UI library 不一樣,它是讓你複製所有的原始碼到你的專案中,你擁有所有的原始碼,未來要修改樣式都是你自己決定,但這意味者你需要花更多心力維護樣式。

接著我們看到一些常見在技術選型中的問題,如果其實說到底 Shadcn UI 是 headless UI + taildwind 的組合,在市面上還是有許多 headless UI 的選擇,如果你要打造自己的元件庫,可以選擇一套 headless UI 並且自己客製化。

在文章的最後提到了在做專案時遇到的兩個問題,第一個是 Shadcn UI 的 form 結構有點怪,第二個是 Shadcn UI 中的 DatePicker 是基於 ReactDayPicker 實作的,該套件沒有 MonthPicker,但這兩個並不是 bugs,而是 features,各位可以評估是否符合你們的需要再考慮要不要導入。

🎉 筆者最近開始經營 Instagram 技術小帳,平時會分享一些網頁開發的知識,歡迎大家
追蹤 @leo.web.dev

--

--

Leo Chiu
手寫筆記

每天進步一點點,在終點遇見更好的自己。 Instragram 小帳:@leo.web.dev