Paris 17th May 2019
credits to @callumacrae
π Vue core team
π¨βπ» Freelance
πParis
import('a_package').then(module => module.default)
import('./utils.js').then(module => module.log)
const aPackage = () => import('a_package')
const utils = () => import('./utils.js')
Sean / Tobias / Johannes
Me
<script type="module">
const utils = () => import('./utils.js')
utils().then(({ log }) => {
log('hey')
})
</script>
import Calendar from '@/components/Calendar.vue'
const Calendar = () => import('@/components/Calendar.vue')
// router.js
const Home = () => import('@/views/Home')
const User = () => import('@/views/User')
const routes = [
{ path: '/', component: Home },
{ path: '/users/:id', component: User },
]
// App.vue
const Search = () => import('@/components/Search')
export default {
components: { Search }
}
Search.vue
PROFIT π₯
import('LoginModal')
import(/* webpackPrefetch: true */ 'LoginModal')
<link rel="prefetch" href="login-modal-chunk.js" />
import(/* webpackPreload: true */ 'ChartingLibrary')
<link rel="preload" href="chunk.js" />
// SomePage.vue
() => import(/* webpackPrefetch: true */ 'LoginModal')
() => import(/* webpackPreload: true */ 'ChartingLibrary')
const SomePage = () => import('./SomePage.vue')
Only works for lazy loaded chunks:
<component :is="dynamicComponent"/>
// inside of a component method
// local or global component
this.dynamicComponent = 'UserCard'
// component descriptor
// import UserCard from './UserCard'
this.dynamicComponent = UserCard
export default {
render (h) {
return h(this.dynamicComponent)
},
methods: {
changeDisplayedComponent () {
this.dynamicComponent = 'UserCard'
// or
this.dynamicComponent = UserCard
}
}
}
import Calendar from '@/components/Calendar.vue'
const Calendar = () => import('@/components/Calendar.vue')
<component :is="dynamicComponent"/>
// inside of a component method
this.dynamicComponent = () => import('./UserCard')
render(h) { return h(this.dynamicComponnet) }
<component :is="() => import('./UserCard')"/>
render(h) {
return h(() => import('./UserCard'))
}
π ββοΈ DON'T β
<component :is="dynamicComponent"/>
// inside of a component method
this.dynamicComponent = () => import('./UserCard')
render(h) { return h(this.dynamicComponnet) }
YES β
import(`@/components/async/${name}.vue`)
let webpack creates chunks π
import('@/components/' + myComponentPath) // π± β οΈ
your app
import('@/components/' + myComponentPath) // π± β οΈ
import(`@/components/Lazy${name}.vue`) // π
import(`@/components/async/${name}.vue`) // π―
<ExamplePreview name="counter"/>
computed: {
demoComponent() {
// make demoComponent depend on name
const name = this.name
return () =>
import(`@docs/examples/${name}/index.js`)
}
}
<component :is="demoComponent"/>
when your app is unmaintainable but you still care
vue ui
// in a component method
this.error = null
return import('./Component.vue').catch(err => {
this.error = err
})
<p class="danger" v-if="error">{{ error }}</p>
this.error = null
this.pending = true
return import('./Component.vue').then(module => {
this.isPending = false
return module
}).catch(err => this.error = err)
<p class="danger" v-if="error">{{ error }}</p>
<p class="info" v-else-if="isPending">Loading...</p>
<div>
<p v-if="error">Error: {{ error.message }}</p>
<p v-else-if="isPending && isDelayElapsed">Loading...</p>
<component v-else :is="dynamicComponent" />
</div>
fetchUsers() {
this.error = null
this.isPending = true
this.isDelayElapsed = false
import('./Component.vue')
.then(m => { this.dynamicComponent = m.default })
.catch(error => { this.error = error })
.finally(() => { this.isPending = false })
setTimeout(() => {
this.isDelayElapsed = true
}, 200)
}
const AsyncComponent = () => ({
component: import('./MyComponent.vue'),
loading: LoadingComponent,
error: ErrorComponent,
delay: 200,
timeout: 3000
})
<Promised
:promise="componentPromise"
#combined="{ isPending, data, error }"
>
<p v-if="error">
{{ error.message}}
</p>
<p v-else-if="isPending">Loading component</p>
<component
v-else
:is="data.default"
/>
</Promised>
π Github repo