-
Notifications
You must be signed in to change notification settings - Fork 1
導入 Tailwind、Victory 以及處理 Vite 建置
Viewed package.json:1-30
這次重構確實涉及了多個層次的技術細節(從前端框架、建置工具到部署流程)。為了幫您消化,我將這次導入 Tailwind、Victory 以及處理 Vite 建置的核心作法總結為以下四個關鍵模塊:
在不使用 CDN (unpkg) 的獨立運行架構下,Tailwind 的處理流程如下:
-
離線編譯:透過
@tailwindcss/cli將src/core/input.css編譯成gen/output.css。這解決了對外連網的依賴。 -
自定義字體:在
input.css中使用@font-face定義您的SpaceFont(指向/font.woff2),並在@theme中將其設定為sans的預設值。 -
資產打包:編譯出的 CSS 不直接在網頁引用,而是由
generate-assets.ts讀取並轉換成 Base64 字串,存放在assets.gen.ts中,最後由 Hono 直接內嵌在 HTML 的<style>標籤中。
Victory 是一個複雜的圖表庫,在 Cloudflare Workers (SSG) 環境下的導入重點:
-
JSX Pragma (解決 Error #31):
這是最關鍵的一點。因為專案同時存在 Hono (SSR) 和 React (Client),Vite 預設可能會用 Hono 的 JSX 轉換器去處理 React 檔案。
-
作法:在
main.tsx最頂端加入/* @jsxImportSource react */。 - 原理:這確保了 Vite 會使用 React 的標準格式來編譯圖表組件,避免 React 在瀏覽器中因讀不到正確的物件格式而崩潰。
-
作法:在
-
模組化 AJAX:建立
api.ts統一處理fetch邏輯,讓 React 組件能非同步獲取資料,確保頁面初始載入(SSG)極快,而圖表則在後端資料回傳後動態渲染。
為了讓專案能獨立運行,我們建立了一套自動化流程:
-
Vite Build:將
main.tsx打包成單一的client.js。 -
Tailwind Build:產出
output.css。 -
Asset Generator (核心):
- 這是一個自研腳本 (
scripts/generate-assets.ts)。 - 它負責:字體子集化 (Subset font)、讀取 JS/CSS/圖片、將它們全部轉為 Base64。
- 最後生成一個
assets.gen.ts供伺服器端 (app.ts) 呼叫。
- 這是一個自研腳本 (
這是最後處理的最混亂但也最重要的部分:
-
目錄隔離:
-
問題:
wrangler dev會監聽src的變動。如果建置產物寫入src/gen,會導致監聽 -> 建置 -> 檔案變動 -> 重新監聽的無限迴圈。 -
作法:將產出目錄移至根目錄的
/gen(與src平級),並在.gitignore忽略它。
-
問題:
-
部署腳本封裝:
- 在
package.json封裝"deploy": "npm run build:assets && wrangler deploy"。 - 這樣不論是在本地手動部署,還是在 Cloudflare Dashboard 的自動化 CI 環境,都能確保「先產出資產,再執行部署」,避免發生
Could not resolve assets.gen.js的錯誤。
- 在
-
React 檔案:一定要記得檢查 JSX 轉換來源 (
reactvshono)。 -
建置產物:永遠不要放在
wrangler正在監聽的原始碼目錄內。 -
環境變數/依賴:改用
package.json的scripts來串接多個建置步驟,比寫在wrangler.jsonc的build塊更穩定且易於本地除錯。
這套作法雖然初期設定較繁瑣,但它建立了一個非常強大的離線優先 (Offline-first) 架構,即便在沒有網路的情況下,只要有 Node.js 環境,您的 Dashboard 就能完整編譯與運作!
有個問題,Vite不是處理網站資源打包嗎?本身不能順便處理Tailwind編譯嗎?我看Build的工具鏈已經很複雜了,我有在想build:css 要做的事情能不能合併進Vite裡?
Viewed package.json:1-30
這是一個非常敏銳的觀察!Vite 本身確實具備極強的 CSS 處理能力,完全可以整合 Tailwind。
目前的工具鏈之所以看起來比較「分開」,是因為我們現在採用的是 Hono (伺服器端) + Vite (客戶端) 的混合架構,這導致了兩個工具在處理 CSS 時的權責稍微重疊了:
-
Vite 的角色:目前 Vite 只負責編譯「瀏覽器跑的 JS」(即 Victory 圖表部分)。它產出的 CSS 通常會被封裝在
dist資料夾裡,並帶有隨機雜湊檔名(例如main-ab12.css)。 -
Hono 的角色:伺服器渲染 (SSR/SSG) 產生的 HTML 外殼(包含導覽列、背景色等)也需要 Tailwind。如果交給 Vite 處理,我們的伺服器端程式碼會很難預測編譯後的 CSS 檔名,這會增加資產打包 (
generate-assets.ts) 的複雜度。 -
Tailwind v4 CLI 的特性:Tailwind v4 標榜「零配置」,它的 CLI 極快且獨立,對於像我們這種需要將 CSS 轉為 Base64 嵌入 Worker 記憶體的專案來說,獨立呼叫 CLI 可以確保我們得到一個路徑固定、內容純淨的
output.css。
如果您希望簡化,確實可以這樣做。方法是導入 Tailwind v4 的 Vite 插件:
-
安裝插件:
npm install @tailwindcss/vite -
修改
vite.config.ts:import tailwindcss from '@tailwindcss/vite'; export default defineConfig({ plugins: [tailwindcss(), react()], // ... });
-
在
main.tsx引入 CSS:import '../input.css'; // 讓 Vite 去追蹤這份 CSS
-
優點:
-
package.json的指令會少一行。 - Vite 可以同時優化 JS 和 CSS(例如進行更深度的樹搖優化)。
-
-
缺點 (在本專案中):
-
路徑問題:Vite 編譯出的 CSS 會躲在
gen/dist/client/assets/底下且檔名不固定。您的generate-assets.ts會需要寫額外的邏輯去「撈」出這份 CSS 檔名,才能把它塞進assets.gen.ts。 - 開發體驗:目前分開跑時,您可以單獨編譯 CSS 而不觸發 Vite 複雜的打包邏輯,這在微調樣式時速度極快。
-
路徑問題:Vite 編譯出的 CSS 會躲在
目前的做法雖然看起來多了一條指令,但它實現了**「關注點分離」**:
- Vite 專心處理複雜的 React/Victory 邏輯。
- Tailwind CLI 專心生產全局樣式。
- Asset Script 專心把兩者打包進 Worker。
如果您覺得指令太多太亂,我建議維持現狀但優化 package.json。其實這也是目前許多高效能專案(如 Remix 或早期 Hono 專案)偏好的做法:讓專業的工具處理專業的事。
除非您的專案規模大到需要 Vite 的高級 CSS 處理功能(例如 CSS Modules 或 PostCSS 插件群),否則目前的「獨立編譯、統一打包」模式其實是最容易維護且效能最高的喔!