송민준의 개발노트

Vue Lazy Loading 본문

웹/Vue

Vue Lazy Loading

송민준 2021. 7. 20. 10:31

Lazy Loading이란?

react, vue와 같은 SPA로 개발을 하면 사용자가 처음 진입 시 프로젝트와 관련된 모든 리소스를 다운 받는다. 그렇다면 현재 보여지는 화면 외에 다른 리소스까지 다운을 받게 되고 이는 프로젝트가 커질 수록 영향을 받게 된다. 이러한 문제를 개선하기 위한 방법이 Lazy Loading이다. 말 그대로 로딩을 지연한다는 것이다.

 

적용 방법은 간단하다. Vue Cli와 같은 도구를 사용하면 빌드 파일을 분리할 수가 있다.

route를 설정하는 파일에서 특정 컴포넌트를 가져올 때 주석으로 webpackChunkName을 추가해주면 된다.

예를 들어 아래와 같이 변경이 가능하다.

// 기존
import Notice from '@/views/board/Notice.vue'
// 변경
const Notice = () => import(/* webpackChunkName: "board" */'@/views/board/Notice.vue');

지연로딩을 위해 프로미스 객체를 화살표 방식으로 간단하게 구현한 것이다.

위에 예시는 vendor와는 다른 board.js 라는 별도의 청크파일로 구성이 된다.(빌드시)

 

Notice라는 컴포넌트 외에도 다른 컴포넌트를 'board'라는 파일에 같이 빌드가 가능하다.

Notice와 관련된 컴포넌트를 같이 구성해주면 된다.

여러개를 나누면 아래와 같이 여러 js파일이 생긴다.

 

지금까지는 route에만 셋팅을 해주었다.

그렇다면 Vue 파일 내의 Component 호출 시에는 적용이 안될까?

정답은 가능하다. 해당 Vue 파일에도 똑같은 문법으로 적용해주면 된다.

 

22. 02. 01 추가 보완

Lazy Loading에서 code split만 한다고 끝이 아니었다.

성능 최적화를 위해 좀 더 고려할 부분이 있었는데 prefetch(스펙 내용) 관련 부분이었다.

 

vue-cli3에서부터 prefetch 기능이 기본으로 설정되었는데 이는 초기에 모든 리소스들을 가져와서 당장 사용하지 않는 리소스는 메모리에 캐싱해 놓는다. 그리고 화면 전환 시 캐싱한 리소스를 불러와 매끄러운 전환이 가능하게 한다.

 

이러한 장점이 있지만 모든 리소스들을 가져오다보니 첫 로딩 시 로드타임에 영향을 주게 된다.

비동기 리소스를 가져오는 것이지만 request  요청이 많다보면 첫 로딩에 반드시 필요한 리소스를 늦게 받을 수도 있다.

미니 프로젝트면 크게 상관 없겠지만 실무에서 프로젝트 규모가 조금만 커져서 큰 차이가 나게 된다.

 

그렇다면 어떻게 하는 것이 가장 좋을까?

결론부터 말하자면 상황에 따라 부분적으로 적용하는게 가장 좋다고 생각한다.

유저의 입장에서 사이트에 접속을 하고 화면 전환을 주로 하는 페이지가 있을 것이고 아닌 페이지가 있을 것이다. 기본 설정으로 전역 prefetch 옵션을 끄고 아래와 같이 적용한다.

1. 자주 전환하는 페이지 : prefetch를 적용해서 좀 더 부드러운 전환을 제공하여 UX를 높인다.

2. 빈도가 적은 페이지 : prefetch 미적용으로 리소스를 줄이고 성능 개선을 한다.

 

적용 예시 코드는 아래와 같다.

* vue.config.js 에서 prefetch 옵션 삭제

 module.exports = {
  chainWebpack: config => {
    config.plugins.delete('prefetch');
  },
 }

* router에서 lazy-loading 적용 (contact 페이지가 유저들이 주로 진입하는 페이지라고 가정)

const routes = [
  생략...
  {
    path: '/about',
    name: 'About',
    // 화면 전환 시 가져옴
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  },
  {
    path: '/contact',
    name: 'Contact',
    // prefetch 적용 -> 첫 로딩 시 가져와서 메모리에 캐싱함.
    component: () => import(/* webpackChunkName: "contact", webpackPrefetch:true */ '../views/Contact.vue')
  }
  생략...
]