Tutorial

Showing Loading & Error States with Vue.js Async Components

Published on March 5, 2018
author

Joshua Bemenderfer

Showing Loading & Error States with Vue.js Async Components

Vue’s first-class support for asynchronous components is great, but not everyone is aware of how to show when an async component is loading or has failed to load. So let’s take a look at how to display error or loading components while we’re waiting for an asynchronous component to load.

Getting Started

Start a simple Vue project with vue-cli and the webpack-simple template.

We’ll be using a dynamic import function that Babel doesn’t support by default, so you’ll need to quickly add a small Babel plugin to get the project to build.

# Yarn
$ yarn add babel-plugin-syntax-dynamic-import -D
# NPM
$ npm install babel-plugin-syntax-dynamic-import --save-dev

Go ahead and edit .babelrc to add that plugin real quick.

.babelrc
{
  "presets": [
    ["env", { "modules": false }],
    "stage-3"
  ],
  plugins": ["syntax-dynamic-import"]
}

Writing the Components

Now let’s go ahead and create three very complex components next to App.vue.

AsyncComponent.vue is what we’ll be loading asynchonously.

AsyncComponent.vue
<template>
  <p>Ohai! I'm an asynchronously-loaded component!</p>
</template>

AsyncLoadError.vue is what we’ll display if something goes terribly wrong.

AsyncLoadError.vue
<template>
  <p>Oh noes! I was unable to load the asynchronous component. Cry face. :'(</p>
</template>

AsyncLoading.vue will display while AsyncComponent.vue is loading.

AsyncLoading.vue
<template>
  <p><em>Loading noises</em></p>
</template>

Async Loading

Now, in App.vue, load the utility components as normal, but use the dynanmic import() syntax for AsyncComponent.vue. This function returns a promise that resolves with the actual data when the network request finished.

Then, register AsyncComponent using an arrow function that returns a configuration object. This object specifies what components to use for loading and error states, and how long to wait before considering the component as having failed to load.

You should now be able to use <async-component></async-component> in your app!


<template>
  <div id="app">
    <img src="./assets/logo.png">
    <h1>{{ msg }}</h1>
    <h2>Essential Links</h2>
    <ul>
      <li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>
      <li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>
      <li><a href="https://chat.vuejs.org" target="_blank">Community Chat</a></li>
      <li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>
    </ul>
    <h2>Ecosystem</h2>
    <ul>
      <li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
      <li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
      <li><a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a></li>
      <li><a href="https://github.com/vuejs/awesome-vue" target="_blank">awesome-vue</a></li>
    </ul>
    
    <async-component></async-component>
  </div>
</template>

<script>
import AsyncLoadError from './AsyncLoadError.vue'
import AsyncLoading from './AsyncLoading.vue'
const AsyncComponent = import('./AsyncComponent.vue')

export default {
  components: {
    AsyncComponent: () => ({
      // The component we want to load.
      component: AsyncComponent,
      // The component to use as a placeholder while the
      // async component is loading.
      loading: AsyncLoading,
      // The component to render instead if there is an error
      // loading the async component.
      error: AsyncLoadError,
      // The delay before the loading component is shown.
      delay: 100,
      // If this timeout is reached, the async component is considered
      // to have failed loading.
      timeout: 3000
    })
  },

  name: 'app',
  data () {
    return {
      msg: 'Welcome to Your Vue.js App'
    }
  }
}
</script>

If you open your browser’s developer tools, you should notice that the asynchronous component is loaded from a different file from the rest of your app. You probably won’t notice the loading and error states unless something goes wrong or you have a very slow network connection, but they will work as well.

TIP: You can test the error state by setting timeout to 0 in the async component configuration object.

That should be all you need!

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Joshua Bemenderfer

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.