Vue Lazy Loading

簡介

  • 在 SPA 模式中,隨著專案規模變大,JS 檔案的加載時間也隨之變長
  • 使用懶加載可以分割程式碼,需要時再載入,減少首次進入頁面加載時間
  • 依靠於打包工具(Vite, Webpack) 代碼分割(Code Splitting)的功能
  • 目的都是為了優化使用者體驗

路由懶加載

  • 將每個路由頁面(Vue 檔案)分割成不同的塊(chunks),在訪問相應路由時才加載

不使用懶加載

  • 所有頁面會在應用載入時一次性加載
import Home from './components/Home.vue'import About from './components/About.vue'import Contact from './components/Contact.vue'const routes = [  { path: '/', component: Home },  { path: '/about', component: About },  { path: '/contact', component: Contact }]

使用懶加載

  • 當進入該路由時,再加載對應檔案
const Home = () => import('./components/Home.vue')const About = () => import('./components/About.vue')const Contact = () => import('./components/Contact.vue')const routes = [  { path: '/', component: Home },  { path: '/about', component: About },  { path: '/contact', component: Contact }]

元件懶加載

  • 當有用到該元件的需求時,再進行載入,減少首次進入頁面加載時間

不使用懶加載

  • 會在首次進入頁面時,一次性全部加載元件

創建MyComponent.vue元件

// MyComponent.vue<template>  <div>    <!-- MyComponent的內容 -->  </div></template><script>export default {  // MyComponent的邏輯}</script>

在父元件中引入

// App.vue<template>  <div>    <MyComponent />  </div></template><script>import MyComponent from './components/MyComponent.vue'export default {  components: {    MyComponent  }}</script>

使用懶加載

  • 在父元件中,使用動態引入,在使用到該元件時才會被加載
<template>  <div>    <MyComponent v-if="isComponentVisible" />  </div></template><script>export default {  data() {    return {      isComponentVisible: false    }  },  mounted() {    // 假設某些條件或事件觸發顯示    setTimeout(() => {      this.isComponentVisible = true    }, 3000)  },  components: {    MyComponent: () => import('./components/MyComponent.vue')  }}</script>

defineAsyncComponent

  • 在 Vue3 當中新增的 API,用於更簡便處理異步元件的 Lazy Loading
  1. 創建異步元件
// AsyncComponent.vue<template>  <div>    <h2>      {{ title }}    </h2>  </div></template><script setup>import { ref } from 'vue'  // 異步元件的邏輯  const title = ref('大家好')  ......</script>
  1. 在父元件中引入
// App.vue<template>  <AsyncComponent v-if="show" />  <button @click="show = true">Show Component</button></template><script setup>import { ref } from 'vue'import { defineAsyncComponent } from 'vue'const show = ref(false)const AsyncComponent = defineAsyncComponent(() => import('./components/AsyncComponent.vue'))</script>
  • 使用defineAsyncComponent時可以自定義一些設定
const AsyncComponent = defineAsyncComponent({  // the loader function  loader: () => import('./components/AsyncComponent.vue'),  // A component to use while the async component is loading  loadingComponent: LoadingComponent,  // Delay before showing the loading component. Default: 200ms.  delay: 200,  // A component to use if the load fails  errorComponent: ErrorComponent,  // The error component will be displayed if a timeout is  // provided and exceeded. Default: Infinity.  timeout: 3000})
  • 可以和Suspense一起使用
  • 加載過程中會顯示#fallback的 Loading...,優先於defineAsyncComponent的設定
<template>  <Suspense v-if="show">    <template #default>      <AsyncComponent />    </template>    <template #fallback> Loading... </template>  </Suspense>  <button @click="show = true">Show Component</button></template>

Webpack 的 Lazy Loading

  • 允許開發者使用特定的語法(如 import())來標記代碼中的分割點
  • 這些分割點告訴 Webpack 在這裡需要將代碼分割成不同的chunks
  • 這些chunks可以被單獨加載
  • 在開發階段和生產階段都會進行完整的應用打包

例如:在 Vue Router 中新增一個路由

  • 會將 Home.vue 及其依賴的代碼打包成一個獨立的chunk
  • 這個chunk在用戶訪問相應路由時才會被加載
const Home = () => import('./Home.vue')

參考資料

# Vue # LazyLoading