MUKI AI Summary
在 Vite 專案中,按需引入檔案可減少不必要的資源載入。使用 Vue Router 的路由懶加載,將每個路由拆分成獨立的 chunk,僅在需要時載入相關檔案。設定 import 動態載入路由,能有效提升效能。
完成路由懶加載後,若發現過大的檔案,可使用 Vite 的 build.rollupOptions.output.manualChunks 手動拆分 node_modules 的 package。對於 element-plus 等框架,使用其內建的按需引入功能。另可透過 vite-plugin-compression 插件進行 gZip 壓縮,減少檔案大小,提升載入速度。...
關於按須引入檔案這個功能,我前前後後卡了很久,都是在專案開發的閒暇之餘研究,因為公司大多是以後台開發為主,比較不需要跑 PageSpeed。
不過還是希望可以按需引入,不然每次載入頁面看到拖了一堆不必要的資料,真的覺得很阿雜 XD。以下記錄我自己按需引入的設定步驟,希望對大家有幫助!
1. 路由懶加載
如果你也是用 Vue Router,那就可以將每個路由拆分成單獨的 chunk,例如 /login
的路由,就有一個 Login.js
的檔案,只有當進入 /login
頁面時,才會載入 Login.js
這隻檔案。
使用方法也很簡單,用 import
動態載入路由即可
▼ 把要按需引用的路由改用 import
動態載入
import { createRouter, createWebHistory } from 'vue-router' const Login = () => import('@/pages/Login.vue') // 改用 import 動態載入 const router = createRouter({ history: createWebHistory(), routes: [{ path: '/login', component: Login }] })
▼ 我其實在這一步卡很久 😂,因為我原本是這樣寫,把 import
寫在裡面,但不知為何 build
的時候就是不會把路由單獨 build
出一個檔案,最後我把它獨立拉出來才成功,但我到現在還是不知道原因 QQ,跪求各路大神指點迷津!
const router = createRouter({ history: createWebHistory(), routes: [{ path: '/login', component: () => import('@/pages/Login.vue') // 原本寫在這,但沒有做用 }] })
其實只要做好這一步,就能實現基本的按需引用了,你會發現 build
專案時,他會幫你把檔案都照著路由拆分:
dist/assets/index.c2e3d9e4.js dist/assets/Home.a4c8a61e.js dist/assets/Area.3c14fb4d.js dist/assets/Dashboard.7131aacd.js dist/assets/Edit.54616d8c.js ...
如此一來,打開 /home
路由,就會載入 Home.a4c8a61e.js
打開 /dashboard
,就會載入 Dashboard.7131aacd.js
,... 依此類推。
參考資料:https://router.vuejs.org/guide/advanced/lazy-loading.html
2. 自己動手拆較大的檔案 (Chunk)
完成路由的懶加載後,可能會在 build 清單看到幾個過大的檔案,像這邊的 shine.3aae3c83.js
有 600多 kb;index.5cd3180a.js
也有 700 多 kb。
這部分的檔案,通常是由 node_modules
產生的,而我們並未對 node_modules
進行拆分,因此他預設會將所有 package 的 JS 合在一起,導致檔案過大。
因為我是用 Vite 框架,所以這邊以 Vite 為例,Vite 不需要再安裝 webpack,他使用的是 build.rollupOptions.output.manualChunks
幫我們手動拆檔,可以參考 rollupjs.org 的介紹
▼ 開啟 vite.config.ts
,使用 build.rollupOptions.output.manualChunks
build: { rollupOptions: { output: { manualChunks: (id) => { // 可以把 id 印出來看,會更清楚知道他的內容 // console.log('id', id) if (id.includes('node_modules')) { const arr = id.toString().split('node_modules/')[1].split('/') switch (arr[0]) { case 'element-plus': return default: return arr[0] } } } } } }
我這邊的做法,是把 node_modules
裡面的所有 package 檔案都拆成一個一個獨立的檔案,命名方式為:package 叫什麼名字,檔案就是什麼名字,例如:dist/static/chunk/axios-95165d17.js
,這個就是 axios
的 package
element plus 使用框架本身支援的按需引入
▼ 參考上述程式碼,可以發現當我的 node_modules
是 'element-plus'
時,我的設定為照原本的拆法不要動,因為我有使用 element-plus 的按需引入,所以他會幫我把元件拆成一個個的 css 以及 js,用到才會載入
▼ 用到的 CSS 或 JS 檔案才會載入,這邊提供 CSS 的截圖以供參考, JS 亦同
3. 使用 gZip 壓縮
▼ 當我們在 build 檔案時,可以看到右側有兩個大小,第一個是實際大小,第二個是如果用了 gzip
壓縮後的大小
▼ vite 有 plugin 可以支援 gzip
壓縮,直接安裝:
$ npm install -D vite-plugin-compression
▼ 在 vite.config.ts
設定你要壓縮的大小,我這邊設定為「原檔超過 50kb 就用 gzip
壓縮」
import viteCompression from 'vite-plugin-compression' export default defineConfig({ plugins: [ viteCompression({ threshold: 50000 // 50kb }) ] })
▼ 再重新 build 一次,就會顯示有壓縮的檔案
確認 gZip 是否有成功執行
最後我們來檢查瀏覽器是否抓得到你的 gZip 檔案吧。
首先,先確認 server 有開啟 gzip
,並且有把 CSS、JavaScript 加入 gzip 的設定中。
▼ 以 nginx 為例,我這邊加入的檔案類型有 text、css、js,以及 json:
http { gzip on; gzip_types text/plain text/css application/json application/javascript; }
設定好之後記得重啟伺服器。
然後把網站的快取清除,重新開啟網頁,打開開發者工具面板,將 Content-Encoding
打開,如果有顯示 就表示有抓到 gzip
囉!