Fast loading speed is essential when creating any web application. A few extra seconds could have a huge impact on the number of users visiting your site. This means that having a fast site is important, not just for ranking well in Google Search Engine, but for having users interact with your webpage.
Vue 3 has introduced several new features to help you achieve this easily through the improvements to the async component API and the new Suspense component. In this article, we will be taking a look at using lazying loading components in Vue 3 to speed up your pages load times.
Check out the youtube video that this article was created for:
In this example app, we have a SecretImage
component that displays an interactive graphic of the Vue logo only when the user is authenticated. To prevent intruders from seeing our most valuable asset, we added a button that toggles the visibility of this component.
<template>
<!-- ... -->
<!-- Large component that uses many libraries -->
<SecretImage v-if="isLoggedIn" />
<!-- ... -->
</template>
<script>
import SecretImage from './components/SecretImage.vue'
export default {
components: { SecretImage }
// ...
}
</script>
While building the SecretImage
we used many complex libraries causing the amount of javascript code to increase. Building our app we can see it creates a large vendors file which we are loaded on our initial request to our site.
Async Components
We can use the new defineAsynComponent
function which comes with Vue 3. All we need to do is pass a function that loads our components. Since Vue comes preconfigured with webpack we can use the dynamic import feature.
<template>
<!-- ... -->
<SecretImage v-if="isLoggedIn" />
<!-- ... -->
</template>
<script>
import { defineAsyncComponent } from 'vue'
const SecretImage = defineAsyncComponent(() =>
import('./components/SecretImage.vue')
)
export default {
components: { SecretImage }
// ...
}
</script>
Now when we build our app we can see a new file has been created and the vendor file has significantly reduced.
Logging back in we can also see a new request being created to loading our SecertImage
component.
Since we are loading this component later there may be a short delay while the lazy-loaded part of your UI is being requested and rendered. We can additionally pass in a loading component property which will be displayed while the component is being loaded.
import { defineAsyncComponent } from 'vue'
import Loading from './components/Loading.vue'
const SecretImage = defineAsyncComponent({
loader: () => import('./components/SecretImage.vue'),
loadingComponent: Loading
})
However, using this approach can be restrictive as it is hard to pass props or slots to the loading component.
Suspense
To add more flexibility we can use the new Suspense
component which allows us to have async loading content as a component in the template. All we have to do is call the Suspense
component and pass in a component for the default and fallback slots.
<template>
<!-- ... -->
<Suspense v-if="isLoggedIn">
<template #default>
<SecretImage />
</template>
<template #fallback>
<Loading />
</template>
</Suspense>
<SecretImage v-if="isLoggedIn" />
<!-- ... -->
</template>
<script>
import { defineAsyncComponent } from 'vue'
import Loading from './components/Loading.vue'
const SecretImage = defineAsyncComponent(() =>
import('./components/SecretImage.vue')
)
export default {
components: { SecretImage, Loading }
// ...
}
</script>
The default slot is displayed when the async content has loaded and the fallback slot is displayed while the state is loading.
Thanks for reading! If you like my post don't forget to follow me and subscribe to my youtube channel!
Top comments (6)
This is sooooo useful! Thanks for sharing.
This is useful! thanks
Than you so much
great!
Do we have any options here for offset the point when lazyloading should load?
If I have short pages to scroll, the component loads still even if its not in viewport.
@onlyplanb
Read Intersection Observer, dev.to/onlyplanb/comment/236h2