VueJS

Async Components in Vue 3

Bilal Haidar
5 min read
Async Components in Vue 3
This article was written over 18 months ago and may contain information that is out of date. Some content may still be relevant, but please refer to official documentation for the latest information.

Async Components have had their roots in the Vue JS framework since the second version release. However, in Vue 3, they've had a revamped facelift and their API is a well defined and clear API interface.

Async components are best used in medium to large apps. When an app is formed out of several hundred components, it's wise not to load all the components at once in a single chunk. Rather, the recommendation is to split the components' packing into a set of smaller packages that get loaded whenever needed asynchronously.

While developing, nothing will change in terms of using and placing components inside the <template> section. However, only importing those components will change slightly. Vue 3 offers an intuitive and clear API to help you define the async components.

In this article, we'll explore the new Async Components API, delve into the details and show it in action.

Async Components In Action

Before we go further, here's a link to the Async Components RFC to keep as a reference for later.

The new API offers the defineAsyncComponent() method that you use to define the Async Components.

This method accepts a callback function. In return, this callback function should return an instance of a Promise.

Async Load Inline Defined Component

In the simplest form, defining a local async component can be done as follows:

import { createApp, defineAsyncComponent } from "./vue.esm-browser";

const LocalComponent = defineAsyncComponent(
  () =>
    new Promise((resolve) => {
      resolve({
        template: `
          <h2>
            This is a local component defined as async!
          </h2>
        `
      });
    })
);

const App = {
  components: {
    LocalComponent
  },
  template: `
    <h1>Local Async Component Vue 3</h1>
    <div class="app">
      <LocalComponent />
    </div>
  `
};

createApp(App).mount("#app");

You can play with this example at codesandbox.io.

Let's focus on the local variable named LocalComponent. This variable is assigned the result of calling the defineAsyncComponent() function. The result is a component named AsyncComponentWrapper that wraps around the loaded component.

The callback passed to defineAsyncComponent() function accepts zero parameters and returns a new Promise.

The Promise in this case, resolves an inline Vue Component using the Object Literal method that defines the template of the component returned.

Figure 1 shows the app running.

local-async-component-vue3

Async Load Standalone Defined Component

The other way to load components async is to have a component defined in its own file and loaded asynchronously when needed.

import { createApp, defineAsyncComponent } from "./vue.esm-browser";

const StandaloneComponent = defineAsyncComponent(() => import("./Standalone"));

const App = {
  components: {
    StandaloneComponent
  },
  template: `
    <h1>Standalone Async Component Vue 3</h1>
    <div class="app">
      <StandaloneComponent />
    </div>
  `
};

createApp(App).mount("#app");

The StandaloneComponent is assigned the result of calling the defineAsyncComponent() function. The result is a component named AsyncComponentWrapper that wraps around the loaded component.

The callback passed to defineAsyncComponent() function returns the Promise result returned by calling the import() function.

The import() function in this context refers to the Dynamic Import feature in JavaScript.

If you are running a Vue 3 app using the Vue CLI then the import() function refers to the Webpack Import function.

Instead of defining the component-to-be-async-loaded inline, the code imports an existing standalone component:

export default {
  name: "Standalone Component",
  template: `
    <h2>
      This is a standalone component loaded asynchronously!
    </h2>
  `
};

Figure 2 shows the app running.

standalone-async-component-vue3

You can play with this example at codesandbox.io

Where to define Async Components?

There are two main forms of defining async components in a Vue app.

You've already seen one form, where the async component is defined locally inside the component.

The other option is to define the async component globally at the app level:

import { createApp, defineAsyncComponent } from "./vue.esm-browser";

const StandaloneComponent = defineAsyncComponent(() => import("./Standalone"));

const App = {
  template: `
    <h1>Standalone Async Component Vue 3</h1>
    <div class="app">
      <stand-alone />
    </div>
  `
};

const app = createApp(App);
app.component("stand-alone", StandaloneComponent);
app.mount("#app");

Figure 3 shows the app running.

globally-defined-async-component-vue3

You can play with this example at codesandbox.io

Async Components API

Defining an async component can take two forms: the simple usage and the options usage.

Simple Usage

So far you've seen how to define an async component the simple way. The defineAsyncComponent() method accepts a callback that returns a Promise.

const StandaloneComponent = defineAsyncComponent(() => import("./Standalone"));

Options Usage

The Async Component API offers a rich API to better control loading components asynchronously.

import { createApp, defineAsyncComponent } from "./vue.esm-browser";
import LoadingComponent from "./LoadingComponent";
import ErrorComponent from "./ErrorComponent";

const StandaloneComponent = defineAsyncComponent({
  loader: () => import("./Standalone"),
  loadingComponent: LoadingComponent,
  errorComponent: ErrorComponent,
  delay: 200, // default: 200
  timeout: 3000, // default: Infinity
  suspensible: false, // default: true
  onError(error, retry, fail, attempts) {
    if (error.message.match(/fetch/) && attempts <= 3) {
      retry();
    } else {
      fail();
    }
  }
});

const App = {
  template: `
    <h1>Options Usage Async Component Vue 3</h1>
    <div class="app">
      <stand-alone />
    </div>
  `
};

const app = createApp(App);

app.component("ErrorComponent", ErrorComponent);
app.component("LoadingComponent", LoadingComponent);

app.component("stand-alone", StandaloneComponent);
app.mount("#app");

You can play with this example at codesandbox.io.

The defineAsyncComponent() method now accepts an object with several options. Let's dissect this object!

  • loader: It's the bread and butter behind the API. The loader returns a Promise to load the component. Now you can clearly see that the simple usage of the API specifies only a loader!

  • loadingComponent: Is one you define to show to the user while the API loads the component asynchronously.

  • errorComponent: You define to show to the user when there is an error loading the component.

  • delay: It's the time elapse before showing the loadingComponent to the user.

  • timeout: It's the time elapsed between requesting the component and having it ready to render to the user.

  • suspensible: By default this property is set to false. This is useful when a <Suspense> component is wrapping a component that makes use of Async Component API to load components asynchronously. If the value of suspensible is set to true, then the <Suspense> component takes precedence in showing a fallback content. The loadingComponent, delay, and other properties of the API will be ignored in this case. If the value was kept false, then the API will take precedence over the <Suspense> component.

You can read more about Suspense in Vue 3.

  • onErorr: This function has been newly added to the Async Component API in Vue 3. It accepts a few parameters: error, retry, fail, and attempts. When the component fails to load, this function is called. error parameter gives details about the error that occurred. retry is a function callback that you can call to try loading the component again. fail is a function callback that you can call to stop any further trials of loading the component. Finally, the attempts are the number of attempts that were carried out in order to load the component.

In brief, that is an introduction to the Async Components API in Vue 3.

About the author

Bilal Haidar

Bilal Haidar

Mentor

Author, Developer, and Mentor: <a href="https://www.amazon.com/Professional-ASP-NET-Security-Membership-Management/dp/0470379308/ref=sr_1_2?ie=UTF8&qid=1536838571&sr=8-2&keywords=bilal+haidar">Professional ASP.NET 3.5 Security, Membership, and Role Management with C# and VB | <a href="https://labs.thisdot.co/resources/ACompleteGuideToVueJSeBook">A Complete Guide to VueJS

Keep reading

View all posts →

Awesome 3D experience with VueJS and TresJS: a beginner's guide

Unleash the power of 3D in your Vue.js projects with Tres.js! The future of immersive web experiences is here. #Vuejs #3Ddevelopment...

Mattia Magi5 mins
Vue3D

3 VueJS Component Libraries Perfect for Beginners

For developers checking out VueJS for the first time, the initial steps are overwhelming, particularly when setting up projects from square one. But don’t worry! The VueJS ecosystem offers a plethora of remarkable component libraries, easing this early obstacle. These three libraries are pre built toolkits, providing beginners with the means to kickstart their VueJS projects effortlessly. Let’s take a look! Quasar Quasar is among the most popular open source component libraries for Vue.js, offering a comprehensive set of ready to use UI components and tools for building responsive web applications and websites. Designed with performance, flexibility, and ease of use in mind, Quasar provides developers with a wide range of customizable components, such as buttons, forms, dialogs, and layouts, along with built in support for themes, internationalization, and accessibility. With its extensive documentation, active community support, and seamless integration with Vue CLI and Vuex, Quasar empowers developers to rapidly prototype and develop high quality Vue.js applications for various platforms, including desktop, mobile, and PWA (Progressive Web Apps). PrimeVue PrimeVue is a popular Vue.js component library offering a wide range of customizable UI components designed for modern web applications. Developed by PrimeTek, it follows Material Design guidelines, ensuring responsiveness and accessibility across devices. With features like theming, internationalization, and advanced functionalities such as lazy loading and drag and drop, PrimeVue provides developers with the tools to create elegant and high performing Vue.js applications efficiently. Supported by clear documentation, demos, and an active community, PrimeVue is an excellent choice for developers seeking to streamline their development process and deliver polished user experiences. Vuetify Vuetify is a powerful Vue.js component library that empowers developers to create elegant and responsive user interfaces with ease. Built according to Google's Material Design guidelines, Vuetify offers a vast collection of customizable UI components, ranging from buttons and cards to navigation bars and data tables. Its comprehensive set of features includes themes, typography, layout grids, and advanced components like dialogues and sliders, enabling developers to quickly build modern web applications that look and feel polished. With extensive documentation, active community support, and ongoing development, Vuetify remains a top choice for Vue.js developers seeking to streamline their workflow and deliver visually stunning user experiences. For newcomers venturing into Vue.js, the initial setup might seem daunting. Thankfully, Vue.js offers a variety of component libraries to simplify this process. Quasar, PrimeVue, and Vuetify are standout options, each providing pre built tools to kickstart projects smoothly. Whether you prefer Quasar's extensive UI components, PrimeVue's Material Design inspired features, or Vuetify's responsive interfaces, these libraries cater to diverse preferences and project requirements. With their clear documentation and active communities, these libraries empower developers to start Vue.js projects confidently and efficiently, enabling Vue developers to create polished user experiences....

2 mins
VuetifyVueQuasar

Understanding Vue.js's <Suspense> and Async Components

In this blog post, we will delve into how <Suspense> and async components work, their benefits, and practical implementation strategies to make your Vue.js applications more efficient and user-friendly...

Jesús Padrón6 mins
VueWeb PerformanceUXJavaScript

Getting started with Vitepress

Create your static blog site using Vitepress. Setup and configure your site in minutes by following this step-by-step tutorial....

Simone Cuomo12 mins
VueViteVitepress