在 Nuxt3 使用 nuxi generate 打包輸出靜態網站的過程中,若沒有特別調教的情形下,會切成過多的 js 檔案,造成單頁請求過量,伺服器記憶體超量的問題。這邊筆記下調教 RollupOptions 的 manualChunks 的細項。
內容
Nuxt 3 搭配 Vite 的輸出靜態網站,其 js 檔案會有機率出現切分過細的情況。以當前 2025 瀏覽器使用量居冠的 Google Chrome 為例,對單一域名網址的請求數同一時間僅有 6 個檔案,過量就需要排隊。因此 js 檔切分過細就不是個好決定。
vite.build.rollupOptions.output.manualChunks
這邊的 callback 函式中傳入的 id,有很大一部分是 node_modules 裡的內容。因此可透過包含某些關鍵字,將其打包成一個檔案即可。
ofetch
Nuxt3 底層 fetch 實作採用的套件,可單獨成一支
dayjs, lodash… 等
知名的第三方,都可各自拆出一支
UI Library
這類的需注意打包時有無自動 Tree-Shaking,如果沒有的話,就得手動指定。一樣可以單獨包成一支檔案
Vue / Vue-Router / Pinia
這三者建議打包在一起成一支核心檔案,以免其他第三方套件或是自身頁面有引入到相關內容時,其 js 檔案並不會加入 import 而導致錯誤像是:Uncaught ReferenceError: Cannot access ‘X’ before initialization
核心概念
只要一個 chunk 被另一個 chunk「import」或「依賴」,那麼它一定會先被加載。因此若 UI Library 有用到 vue 的核心功能,那就得確保 Vue 的核心相關檔案都是放在同一支 js 內。
如何檢查
可以在 nuxt.config.ts 的設定檔中,以 build.analyze: true 的情況下,執行 nuxi build 指令。之後你就可以在專案根目錄下的 .nuxt/analyze 資料夾中,找到 client.html 檔案並開啟預覽即可
程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
{ build: { rollupOptions: { output: { manualChunks: (id) => { if (id.includes('node_modules')) { if (id.includes('ofetch')) return 'ofetch' if (id.includes('dayjs')) return 'dayjs' if (id.includes('lodash-es')) return 'lodash' if (id.includes('primevue')) return 'primevue' if (id.match(/node_modules\/(vue|@vue|vue-router|pinia)\//)) return 'core' return 'vendor' } }, }, }, } } |
參考資料
1. nuxt3构建优化
2. Some chunks are larger than 500 KiB after minification
3. VueTorrent
4. Vite打包分割代码