Nuxt 번들 로딩 최적화 & auto import (@nuxt/components)

고성곤·2022년 9월 6일
1

개요

지금 재직 중인 회사에 입사하고 나서 얼마 지나지 않아서 Nuxt로 만들어진 프로젝트의 로딩 타임을 최적화하는 업무를 받았다.
로딩 과정을 조사하던 중에 특이한 점을 발견했다.

  • 불러오는 js 파일의 갯수가 지나치게 많다.
  • 현재 페이지에서 사용하지 않는 컴포넌트도 함께 로딩된다.

이상한 점을 느껴서 찾아보니 Nuxt에 auto import 옵션이 있다는 것을 알게 되었다.
이 옵션은 명시적으로 컴포넌트를 import할 필요 없이 자동으로 import를 해주는 옵션인데 이 프로젝트에서도 사용하고 있었다.
nuxt.config.jscomponents: false를 세팅해서 auto import를 끈 뒤에 위 증상이 해결되었고(명시적으로 컴포넌트를 import하고 있었기 때문에 auto import를 꺼도 문제가 없었다) 불러오는 js 번들 사이즈가 큰 폭으로 줄었다(1.3MB -> 410KB).

일단 문제는 해결되었지만, 의아한 점이 있었다.

  • 왜 사용하지 않는 컴포넌트를 미리 로딩할까?

이 문제에 대해 잊고 있었는데 이력서를 정리하던 중 다시 생각이 났고 이번 기회에 좀 더 자세하기 조사해보았다.

Nuxt가 컴포넌트를 미리 로딩하는 케이스

  1. prefetchLinks
    Nuxt 2.4 버전부터 도입된 기능으로, <RouterLink> 대신 <NuxtLink> 컴포넌트를 사용하면 <NuxtLink> 컴포넌트가 보이는 시점에(IntersectionObserver를 사용한다) 이동할 페이지의 컴포넌트를 미리 로딩한다. prefetchLinks 옵션은 기본적으로 활성화 되어 있다.
    하지만 프로젝트에서 <NuxtLink> 컴포넌트를 사용하고 있지 않았기 때문에 해당사항이 없었다.

  2. @nuxt/components (auto import components)
    앞서 설명한대로 컴포넌트를 자동으로 import하는 기능이다. 공식 문서에는 기본적으로 꺼져있다고 쓰여있지만, create-nuxt-app을 사용해서 nuxt 프로젝트를 생성하면 명시적으로 components: true가 정의되어 있다.
    이 옵션이 켜져 있으면 기본적으로 모든 컴포넌트를 검색한 다음 .nuxt/components/index.js 에 이 컴포넌트들을 import 하는 코드가 생성된다.

import { wrapFunctional } from './utils'

export const Dummy = import('../../components/Dummy.vue' /* webpackChunkName: "components/dummy" */).then(c => wrapFunctional(c.default || c))
export const NuxtLogo = import('../../components/NuxtLogo.vue' /* webpackChunkName: "components/nuxt-logo" */).then(c => wrapFunctional(c.default || c))
export const PleaseDoNotLoad = import('../../components/PleaseDoNotLoad.vue' /* webpackChunkName: "components/please-do-not-load" */).then(c => wrapFunctional(c.default || c))
export const Tutorial = import('../../components/Tutorial.vue' /* webpackChunkName: "components/tutorial" */).then(c => wrapFunctional(c.default || c))
export const VuetifyLogo = import('../../components/VuetifyLogo.vue' /* webpackChunkName: "components/vuetify-logo" */).then(c => wrapFunctional(c.default || c))

문제는 여기서 컴포넌트를 import할 때 async import를 사용하지 않고 있다는 점이다(isAsync 옵션을 켜면 async import를 사용할 수 있다. 2.2.0까지는 기본적으로 꺼져있다). 이 코드가 실행되는 시점에 프로젝트 내의 모든 컴포넌트가 사용 여부와 무관하게 로딩된다.

그런데 지금 시점(2022/09/06) 기준으로는 create-nuxt-app으로 Nuxt 프로젝트를 생성했을 때 2번의 이슈가 재현되지 않았다.
@nuxt/components 버전이 2.2.1로 올라가면서 컴포넌트 로딩에 async import를 디폴트로 사용하도록 변경되었기 때문에 예전처럼 모든 컴포넌트가 동시에 로딩되는 것이 아니라 사용 시점에 로딩되고, 번들 로딩을 보다 효율적으로 할 수 있게 되었다.

결론

  • 2.2.1 이전의 @nuxt/components를 사용하고 있다면 2.2.1로 업데이트하자
  • 필요하지 않다면 prefetchLinks 또는 components 옵션을 끄자

0개의 댓글