[Vue.js] Router - Component Lazy Loading

camille·2023년 1월 15일

Single Page Application의 가장 큰 특징으로 페이지 진입시 리소스를 한번에 다운을 받아서 자연스러운 페이지 전환을 시켜 준다는 것이다.
하지만 프로젝트의 규모가 커지면 커질 수 록 리소스 다운로드에 많은 시간이 소요되어서 SPA의 장점이자 단점으로 작용한다. SPA의 대표적인 프레임워크/라이브러리로 꼽히는 Angular, React, Vue에서는 이와 같은 단점을 보완하기 위해 지연된 로딩(Lazy Loading)을 활용한다.

Lazy Loading

지연된 로딩이란 해당 기능이 필요한 타이밍에 로딩하여 사용하는 방법으로, 불필요하게 index페이지에서 당장 사용하지 않는 리소스 다운 시간을 단축시켜 준다.

Vue Router - Component Import

lazy-loaded 사용한 경우

import MainPage from './components/MainPage.vue'
import InfoPage from './components/InfoPage.vue'
import PurchasePage from './components/PurchasePage.vue'

const router = new VueRouter({
  routes: [
    { path: '/main', component: MainPage },
    { path: '/info', component: InfoPage },
    { path: '/purchase', component: PurchasePage }
  ]
})

상단에서 MainPage, InfoPage, PurchasePage를 모두 import하고 있기 때문에 해당 경로에 진입하지 않더라도 모든 컴포넌트 리소스를 다운받게된다. 규모가 작은 프로젝트라면 이렇게 하더라도 큰 문제가 없겠지만 규모가 커질수록 이와 같은 코드는 성능적으로 문제가 생기게 된다.

const router = new VueRouter({
  routes: [
    { path: '/main', component: () => import('./components/MainPage.vue') },
    { path: '/info', component: () => import('./components/InfoPage.vue')},
    { path: '/purchase', component: () => import('./components/PurchasePage.vue') }
  ]
})

위와 같이 컴포넌트 import 코드를 routes 내에서 하면 해당 경로로 들어왔을 때 리소스를 다운받게 된다. 라우트 설정에 컴포넌트를 반환하는 함수를 정의하면 매칭되는 경로로 들어왔을 때 컴포넌트를 import와 함께 반환하게 된다.

개발자 콘솔을 열어서 확인해보면 경로가 매칭될 때 마다 다운 받는 것을 알수 있다.

동일한 Chunk로 컴포넌트 그룹핑하기

vue-lazy-load/src/App.vue 수정

<template>
  <div id="nav">
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link to="/one">One</router-link> |
    <router-link to="/two">Two</router-link> |
    <router-link to="/three">Three</router-link>
  </div>
  <router-view/>
</template>

<style>

views 폴더에 컴포넌트 생성

<template>
  <div class="one">
    <h1>This is an one page</h1>
  </div>
</template>

two, three같은 경우에도 위와 같이 생성

/src/router/index.js 파일 수정

one, two, three를 라우터에 추가해준 뒤 해당 라우터는 특별한 주석을 / webpackChunkName: "num" / 로 동일하게 하여 그룹핑해 준다.

import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  },
  {
    path: '/one',
    name: 'One',
    component: () => import(/* webpackChunkName: "num" */ '../views/One.vue')
  },
  {
    path: '/two',
    name: 'Two',
    component: () => import(/* webpackChunkName: "num" */ '../views/Two.vue')
  },
  {
    path: '/three',
    name: 'Three',
    component: () => import(/* webpackChunkName: "num" */ '../views/Three.vue')
  }

]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

그룹핑된 One, Two, Three 메뉴는 One에서 num.js 호출하고 그 뒤로는 호출하지 않는 것을 확인 수 있다.

0개의 댓글