지금 재직 중인 회사에 입사하고 나서 얼마 지나지 않아서 Nuxt로 만들어진 프로젝트의 로딩 타임을 최적화하는 업무를 받았다.
로딩 과정을 조사하던 중에 특이한 점을 발견했다.
이상한 점을 느껴서 찾아보니 Nuxt에 auto import 옵션이 있다는 것을 알게 되었다.
이 옵션은 명시적으로 컴포넌트를 import할 필요 없이 자동으로 import를 해주는 옵션인데 이 프로젝트에서도 사용하고 있었다.
nuxt.config.js
에 components: false
를 세팅해서 auto import를 끈 뒤에 위 증상이 해결되었고(명시적으로 컴포넌트를 import하고 있었기 때문에 auto import를 꺼도 문제가 없었다) 불러오는 js 번들 사이즈가 큰 폭으로 줄었다(1.3MB -> 410KB).
일단 문제는 해결되었지만, 의아한 점이 있었다.
이 문제에 대해 잊고 있었는데 이력서를 정리하던 중 다시 생각이 났고 이번 기회에 좀 더 자세하기 조사해보았다.
prefetchLinks
Nuxt 2.4 버전부터 도입된 기능으로, <RouterLink>
대신 <NuxtLink>
컴포넌트를 사용하면 <NuxtLink>
컴포넌트가 보이는 시점에(IntersectionObserver
를 사용한다) 이동할 페이지의 컴포넌트를 미리 로딩한다. prefetchLinks
옵션은 기본적으로 활성화 되어 있다.
하지만 프로젝트에서 <NuxtLink>
컴포넌트를 사용하고 있지 않았기 때문에 해당사항이 없었다.
@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를 디폴트로 사용하도록 변경되었기 때문에 예전처럼 모든 컴포넌트가 동시에 로딩되는 것이 아니라 사용 시점에 로딩되고, 번들 로딩을 보다 효율적으로 할 수 있게 되었다.
@nuxt/components
를 사용하고 있다면 2.2.1로 업데이트하자prefetchLinks
또는 components
옵션을 끄자