라우트 지연 로딩
번들러로 앱을 빌드하면 JavaScript 번들이 꽤 커질 수 있고, 이는 페이지 로드 시간에 영향을 줍니다. 각 라우트의 컴포넌트를 별도 청크로 분리하고 해당 라우트를 방문했을 때만 로드할 수 있다면 더 효율적일 것입니다.
Vue Router는 dynamic import를 기본 지원하므로, 정적 import를 동적 import로 바꿀 수 있습니다:
// 다음을
// import UserDetails from './views/UserDetails.vue'
// 이렇게 바꿉니다
const UserDetails = () => import('./views/UserDetails.vue')
const router = createRouter({
// ...
routes: [
{ path: '/users/:id', component: UserDetails },
// 또는 라우트 정의에서 직접 사용하세요
{ path: '/users/:id', component: () => import('./views/UserDetails.vue') },
],
})component(및 components) 옵션은 컴포넌트 Promise를 반환하는 함수를 받으며, Vue Router는 해당 페이지에 처음 진입할 때만 이를 가져온 뒤 캐시된 버전을 사용합니다. 즉 Promise를 반환하기만 한다면 더 복잡한 함수도 사용할 수 있습니다:
const UserDetails = () =>
Promise.resolve({
/* 컴포넌트 정의 */
})일반적으로는 모든 라우트에 대해 항상 동적 import를 사용하는 것이 좋습니다.
Vite나 webpack 같은 번들러를 사용하면 이는 자동으로 코드 분할의 이점을 얻게 됩니다.
async 컴포넌트와의 관계
Vue Router의 지연 로딩은 Vue의 async 컴포넌트와 비슷해 보일 수 있지만, 둘은 별개의 기능입니다. async 컴포넌트를 라우트 컴포넌트로 사용하지 마세요. async 컴포넌트는 라우트 컴포넌트 안에서 사용할 수는 있지만, 라우트 컴포넌트 자체는 단순히 함수여야 합니다.
함수형 컴포넌트와의 관계
흔한 경우는 아니지만 함수형 컴포넌트를 라우트 컴포넌트로 사용할 수 있습니다. 하지만 Vue Router는 함수형 컴포넌트와 지연 로딩을 구분할 방법이 필요합니다. 함수형 컴포넌트를 사용하려면 함수에 displayName을 부여해야 합니다:
const AboutPage: FunctionalComponent = () => {
return h('h1', {}, 'About')
}
AboutPage.displayName = 'AboutPage'같은 청크로 컴포넌트 묶기
같은 라우트 아래 중첩된 모든 컴포넌트를 같은 청크로 묶어, 한 번의 요청으로 모두 로드되게 하고 싶을 수 있습니다.
Vite에서
rollupOptions 아래에서 청크를 정의할 수 있습니다:
export default defineConfig({
build: {
rollupOptions: {
// https://rollupjs.org/guide/en/#outputmanualchunks
output: {
manualChunks: {
'group-user': [
'./src/UserDetails',
'./src/UserDashboard',
'./src/UserProfileEdit',
],
},
},
},
},
})webpack에서
chunk 이름을 특수 주석 문법으로 지정할 수 있습니다:
const UserDetails = () =>
import(/* webpackChunkName: "group-user" */ './UserDetails.vue')
const UserDashboard = () =>
import(/* webpackChunkName: "group-user" */ './UserDashboard.vue')
const UserProfileEdit = () =>
import(/* webpackChunkName: "group-user" */ './UserProfileEdit.vue')webpack은 같은 chunk 이름을 가진 모든 async 모듈을 동일한 async chunk로 묶습니다.