效能優化:路由懶加載 (Lazy Loading)
如果你的 Vue 專案有 50 個頁面,而使用者只是想看首頁。這時如果瀏覽器把這 50 個頁面的程式碼全部下載下來,那首屏載入速度絕對會慢到令人髮指。
路由懶加載 (Lazy Loading) 就是來解決這個問題的:只有當使用者真的點擊了某個路由,才去下載該頁面的程式碼。
一、 靜態 vs 動態 Import
❌ 靜態導入 (不推薦)
這是最直覺的寫法,但它會把所有組件打包進同一個 JS 檔案 (index.js)。
javascript
import Home from "../views/Home.vue";
import About from "../views/About.vue";
import User from "../views/User.vue";
const routes = [
{ path: "/", component: Home },
{ path: "/about", component: About },
{ path: "/user", component: User },
];✅ 動態導入 (推薦)
Vue Router 支援使用動態 import() 語法。
javascript
const routes = [
{
path: "/",
name: "Home",
// 只有訪問首頁時,才加載 Home.vue
component: () => import("../views/Home.vue"),
},
{
path: "/about",
name: "About",
component: () => import("../views/About.vue"),
},
];當你這樣寫時,打包工具 (Vite/Webpack) 會自動把 Home.vue 分割成一個獨立的 JS 檔案 (例如 Home.12345.js)。
二、 分包策略 (Chunking)
有時候我們不希望每個頁面都切得太碎 (會導致過多的 HTTP 請求)。我們可能希望把「同一個功能模組」的頁面打包在一起。
例如:UserList, UserDetail, UserEdit 這三個頁面,使用者通常會連續訪問。我們希望載入其中一個時,順便把其他兩個也載入進來 (Preload)。
在 Vite 中 (基於 Rollup)
使用 Rollup 的動態導入註釋。
javascript
const UserList = () => import("../views/UserList.vue");
const UserDetail = () => import("../views/UserDetail.vue");
// 目前 Vite (Rollup) 預設會自動根據 import 分析 chunks
// 但如果你想強制分組,可以在 vite.config.js 中配置 manualChunks在 Webpack 中
使用 Magic Comments。
javascript
const UserList = () =>
import(/* webpackChunkName: "group-user" */ "../views/UserList.vue");
const UserDetail = () =>
import(/* webpackChunkName: "group-user" */ "../views/UserDetail.vue");
const UserEdit = () =>
import(/* webpackChunkName: "group-user" */ "../views/UserEdit.vue");加上這個註釋後,Webpack 會把這三個組件打包成同一個 group-user.js。
三、 載入狀態 (Loading State)
當使用者點擊連結,到 JS 下載完成並渲染之間,會有一段空白時間。
雖然 Vue Router 沒有內建 Loading 指示器,但我們可以用 vue-router 的 非同步組件 特性,或者直接在全域守衛處理。
極簡 Loading 條 (NProgress)
這是一個業界標準做法。
javascript
import NProgress from "nprogress";
import "nprogress/nprogress.css";
router.beforeEach((to, from) => {
// 開始進度條
NProgress.start();
});
router.afterEach(() => {
// 結束進度條
NProgress.done();
});這樣每次切換路由(下載 JS)時,頂部就會有一條細細的進度條跑過去,給使用者很好的反饋。
總結
- 務必使用
() => import(...)來定義路由組件。 - 這會大幅減少首屏加載時間 (LCP)。
- 利用分包 (Chunking) 策略來優化相關頁面的載入體驗。
下一章,也是本系列的最後一章,我們將稍微窺探一下 Vue Router 的內部原理,並總結 Composition API 的最佳實踐。