Lazy loading a specific component in Vue.js

Viewed 4489

I just make it quick: In normal loading of a component (for example "Picker" component from emoji-mart-vue package) this syntax should be used:

import {Picker} from "./emoji-mart-vue";

Vue.component("picker", Picker);

And it works just fine. But when I try to lazy load this component I'm not sure exactly what code to write. Note that the following syntax which is written in the documentation doesn't work in this case as expected:

let Picker = ()=>import("./emoji-mart-vue");
2 Answers

The problem, I'm assuming, is that you're using

let Picker = ()=>import("./emoji-mart-vue");
Vue.component("picker", Picker);

to be clear, you're defining the component directly before the promise is resolved, so the component is assigned a promise, rather than a resolved component.

The solution is not clear and depends on "what are you trying to accomplish"

One possible solution:

import("./emoji-mart-vue")
  .then(Picker=> {
    Vue.component("picker", Picker);
    // other vue stuff
  });

This will (block) wait until the component is loaded before loading rest of the application. IMHO, this defeats the purpose of code-spliting, since the application overall load time is likely worse.

Another option

is to load it on the component that needs it.

so you could put this into the .vue sfc that uses it:

export default {
  components: {
    Picker: () => import("./emoji-mart-vue")
  }
};

But this would make it so that all components that use it need to have this added, however, this may have benefits in code-splitting, since it will load only when needed the 1st time, so if user lands on a route that doesn't require it, the load time will be faster.

A witty way to solve it

can be done by using a placeholder component while the other one loads

const Picker= () => ({
  component: import("./emoji-mart-vue"),
  loading: SomeLoadingComponent
});
Vue.component("picker", Picker);

or if you don't want to load another component (SomeLoadingComponent), you can pass a template like this

const Picker= () => ({
  component: import("./emoji-mart-vue"),
  loading: {template:`<h1>LOADING</h1>`},
});
Vue.component("picker", Picker);

In PluginPicker.vue you do this:

<template>
  <picker />
</template>

<script>
  import { Picker } from "./emoji-mart-vue";
  export default {
    components: { Picker }
  }
</script>

And in comp where you like to lazy load do this: The component will not be loaded until it is required in the DOM, which is as soon as the v-if value changes to true.

<template>
  <div>
    <plugin-picker v-if="compLoaded" />
  </div>
</template>

<script>
const PluginPicker = () => import('./PluginPicker.vue')
export default {
  data() = { return { compLoaded: false }}
  components: { PluginPicker }
}

// Another syntax
export default {
  components: {
    PluginPicker: () => import('./PluginPicker.vue')
  }
}
</script>
Related