在使用 Astro + UnoCSS 建構內容驅動網站時,我遇到了一個非常惱人的錯誤:
Error: EMFILE: too many open files, open 'node_modules/caniuse-lite/data/regions/XX.js'
這個錯誤導致開發伺服器無法啟動,即使提升 ulimit
上限也只能暫時解決。最終我發現,根本原因來自 UnoCSS 掃描過廣的檔案系統路徑設定。以下是完整的除錯過程與解法分享。
問題背景:Astro 開發模式報錯 EMFILE
在執行 npx astro dev
時,錯誤訊息如下:
Error: EMFILE: too many open files, open '.../caniuse-lite/data/regions/NL.js'
同時,CHOKIDAR_DEBUG
和 ulimit -n
無法根本解決問題,代表有某個套件開啟過多檔案。
找出元兇:UnoCSS 掃描整個專案目錄
我的原始 uno.config.ts
設定如下:
export default defineConfig<Theme>({
content: {
filesystem: ["**/*.{html,js,ts,jsx,tsx,vue,astro,md}"], // 🚨 問題所在
},
presets: [presetWind3()],
});
這個設定會讓 UnoCSS 掃描整個專案,包括 node_modules
、.git
、public
和 .cache
等目錄。這種廣泛的掃描範圍導致了嚴重的效能問題。
特別是 node_modules
目錄中的 caniuse-lite
套件,它被 Autoprefixer 廣泛使用。當 UnoCSS 試圖掃描這個目錄時,會開啟大量檔案,最終導致系統達到 open()
函數的數量上限,引發 EMFILE
錯誤。
這種設定不僅會大幅降低開發環境的效能,還可能造成系統資源的過度消耗。因此,限制 UnoCSS 的掃描範圍成為解決這個問題的關鍵。
解法:限制 UnoCSS 掃描範圍
將掃描路徑限制在 ./src/
資料夾內即可解決問題:
import { defineConfig, presetWind3 } from "unocss";
import type { PresetWind3Theme as Theme } from "unocss";
export default defineConfig<Theme>({
content: {
filesystem: ["./src/**/*.{html,js,ts,jsx,tsx,vue,astro,md}"], // ✅ 正確作法
},
presets: [presetWind3()],
});
建議同時搭配排除項目以確保穩定性:
import { defineConfig, presetWind3 } from "unocss";
import type { PresetWind3Theme as Theme } from "unocss";
export default defineConfig<Theme>({
content: {
filesystem: ["./src/**/*.{html,js,ts,jsx,tsx,vue,astro,md}"],
pipeline: {
exclude: ["node_modules", ".git", "public", "dist", ".cache"],
},
},
presets: [presetWind3()],
});
總結
這次的 Debug 經驗讓我深刻理解到,效能優化不僅僅依賴硬體資源,更重要的是正確的配置和合理的邊界設定。UnoCSS 的掃描範圍應該限制在 src/
目錄內,同時搭配 exclude
選項來避免掃描大型資料夾如 node_modules
。此外,遇到 EMFILE
錯誤時,應優先檢查 chokidar、UnoCSS、Tailwind 等工具的掃描行為。
對於在 macOS 上頻繁遇到此類問題的開發者,可以考慮永久提升 ulimit -n
的值。然而,最關鍵的是要謹記:永遠不要讓 UnoCSS 掃描整個專案根目錄。通過這些經驗教訓,我希望能幫助其他 Astro + UnoCSS 開發者避免陷入相同的陷阱,從而提高開發效率和項目穩定性。