본문 바로가기
vue.js/기술

[vue] 비동기 컴퍼넌트 lazy loading | _defineAsyncComponent()

by 냉면돈가스 2022. 4. 14.

LAZY LOADING

 

spa의 단점 중 하나는 처음 웹에 진입 시 번들해놓은 모든 리소스를 한번에 받아 초기 진입속도가 느리다는 점이다.

개발자도구 - network 탭을 보면 chunk-vendors란 메뉴가 있는데,

 chunk-vendors가 맨 처음 리소스를 받는 것이고,

lazy loading는 이 chunk-vendors의 용량을 컴퍼넌트 단위로 나누어 다른 화면에서 리소스를 받도록합니다.

component: () => import(/*webpackChunkName: "about" */ '../views/About.vue')

위 코드처럼 작성할 시 별도의 chunk 파일을 생성하여 실제 이 라우트를 방문했을 때 리소스를 로드하게 됨

다만 lazy loading를 남발할 시 spa의 첫 로딩 후 화면전환 속도가 빠르다는 장점이 사라질 수 있으니 유의

vue에서 lazy load를 사용하여 컴포넌트를 import 하였다면 내부적으로 vue cli3의 prefetch 기능이 사용된 것

prefetch는 비동기 컴퍼넌트를 캐시에 저장하여 사용자가 접속하였을 때 빠르게 리소스를 내려줄 수 있습니다.

굉장히 유용한 기능이지만 사용하지 않을 컴퍼넌트라도 캐시에 담아버려 오히려 랜더링 시간이 늘어 날 수 있음

vue cli에서 prefetch 기능은 기본값으로 true가 설정되어 있어 lazy load가 적용된 컴퍼넌트는 모두 prefetch기능으로 캐시에 저장됨

prefetch 기능을 사용하면 첫화면에서 사용되는 리소스를 가장 나중에 다운받게 되어 있어

초기 랜더링은 prefetch를 사용하지 않았을 시 더 빠름

그래서 초기랜더링속도를 생각하고, prefetch기능을 사용하는 컴퍼넌트가 용량이 크지 않다면 prefetch기능을 끄는 것도 생각해 봄직 함

=> root경로에 vue.config.js 파일을 생성후 삭제

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

 

1000kb 속도에서 test 결과

첫 페이지 입장시 app.js 로딩시간이 1초 가량 단축되었고

데이터가 많은 컴퍼넌트 호출시 기존의 컴퍼넌트와 달리 대기시간이 추가로 필요한게 체감되었다 ㅎㅎ

 

# 추가적으로 테스트 하던중 lazy-loding 사용법에 문제가 있었단걸 알게됨

component: () => import(/*webpackChunkName: "about" */ '../views/Test.vue')
==========================================================================
component: () => import('../views/Test.vue')

구분선 위의 코드를 아래와 같이 바꾸어도 해당 컴퍼넌트 입장할 시에 데이터를 요청하는 문제가 있어

내 의도와는 다른 동작이여서 사용법을 더 알아보니

https://yunzema.tistory.com/274

 

vue code splitting 관련 - vue cli 3의 prefetch 비활성화

vue로 개발 중 code splitting을 하면서 가장 기본적으로 하는 것이 router에서 혹은 component내에서 component의 dynamic import를 활용하는 것이다. import aDialog from 'Views/dialogs/aDialog'; //기본 impo..

yunzema.tistory.com

위 블로그에 글을보고 코드를 수정해봄

( vue.config.js에서 webpackPrefetch 기능은 delete 한 상태에서 수정 )

component: () => import(/* webpackPrefetch: true */ '../views/Test.vue')

더 정확한 테스트를 위해 컴퍼넌트를 추가

  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue')
  },
  {
    path: '/test',
    name: 'Test',
    component: () => import(/* webpackPrefetch: true */ '../views/Test.vue')
  }

 

About은 webpackPrefetch 기능을 사용하지 않아 해당 컴퍼넌트 진입시에 데이터가 요청되고

Test는 기능을 사용하여 미리 캐시에 저장된 데이터를 바로 가져와 속도가 빠르다


defineAsyncComponent 

 

defineAsyncComponent 메소드와 lazy loading 기술의 차이점은

라우터 단위가 아닌 한 컴퍼넌트 안에서도 동적으로 컴퍼넌트 데이터들을 요구할 수 있다는 것이다.

어떻게하냐면 간단함.

 

defineAsyncComponent를 vue에서 import 한 후,

컴퍼넌트마다 형식을 아래와 같이 바꾸어주면됨.

<template>
  <div>
    <button
      @click="
        wC === 'hello-world' ? (wC = 'hello-world2') : (wC = 'hello-world')
      "
    ></button>
  </div>
  <HelloWorld msg="Vite + Vue" v-if="wC === 'hello-world'" />
  <HelloWorld2 msg="Vite + Vue" v-else />
</template>

<script setup>
import { defineAsyncComponent, ref } from "vue";

const HelloWorld = defineAsyncComponent(() => {
  return import("./components/HelloWorld.vue");
});
const HelloWorld2 = defineAsyncComponent(() => {
  return import("./components/HelloWorld2.vue");
});
const wC = ref("hello-world");
</script>

 

 

그 다음 helloworld, helloworld2 컴퍼넌트들을 동적으로 변경,호출하게 만들었고 네트워크탭을 살펴봤다.

맨처음 helloworld만 호출한 모습이다.

helloworld2파일은 캐시에 저장 후 불러오지 않았다.

 

그 다음 버튼을 눌러 wC 데이터를 "HelloWorld2" 로 바꾸어주면

 

이렇게 helloWorld 데이터가 불려온다.

그런데 미리 캐시에 저장한 상태라 속도를 늦춰봐도 속도차이는 별로 못 느꼈음

 

'vue.js > 기술' 카테고리의 다른 글

[vue] vuetify 실행해보기  (0) 2022.07.01
[vue] plugin 제작/실행  (0) 2022.05.03
[vue] 클래스 바인딩하는 여러 방법  (0) 2022.04.12
차세대 빌드 도구 vite (vue)  (1) 2022.04.07
[vue] 이벤트 버블링 관련 수식어  (0) 2022.03.17

댓글