Get Started with Nuxt with Debbie O'Brien

Nuxt Auto Components and Lazy Loading

In a previous lesson we used the fetch hook to fetch our list of planets on the index page. Wouldn't it be nice to also have that list of planets on each planet page so we don't have to click back to the home page to change planets. Instead of duplicating our code we can create a component instead. The fetch hook can be used in components whereas asyncData can only be used on page components.

Lets create a new component called PlanetsList.vue inside our components directory. In our template tag we need to add a div and then paste in our code from our index page. We can remove the link to non existent nuxt planet.

<template>
  <div>
    <p v-if="$fetchState.pending">Fetching planets....</p>
    <p v-else-if="$fetchState.error">Error while fetching planets</p>
    <ul v-else>
      <li v-for="planet in planets" :key="planet.slug">
        <NuxtLink :to="planet.slug">
          {{ planet.title }}
        </NuxtLink>
      </li>
    </ul>
  </div>
</template>

Now we need to cut our script tag from our index page and paste that into our component. By adding the fetch call direct in our component we don't have to add any props.

<script>
export default {
  async fetch() {
    this.planets = await fetch('https://api.nuxtjs.dev/planets').then((res) =>
      res.json()
    )
  },
  data() {
    return {
      planets: [],
    }
  },
}
</script>

We can now use our component direct in our index page and lets add it to our slug page too.

<PlanetsList />

Let's check it out in the browser. And as you can see our component has been added. We can check this out in the Vue dev tools and we can see our list of planets is now coming from our component.

show in vue dev tools

But hang on a second. We didn't import the component. How is it even working?

With Nuxt we don't have to import components once components is set to true in our nuxt.config.

show nuxt config

If we set this to false, we will have no component loaded.

change to false and show in browser

Then in order to see our component we would have to import it and add our component to the component object.

<script>
import PlanetsList from '~/components/PlanetsList'
export default {
  components: {
    PlanetsList,
  },
}
</script>

That's a lot of extra work especially when adding lots of components so let's remove it and set our components back to true. By setting it to true, Nuxt parses our template and automatically includes the components for us. As Nuxt uses webpack for automatic code splitting, the bundle will only contain the components that are used on that page. If you use a component on more than 2 pages, Nuxt will automatically create a shared chunk for them. Very cool

remove imports and change to true show browser

But what if we wanted to lazy load our component. Lazy loading will highly improve your performance especially for those components that are below the fold or only available when clicked. If we are not using any import statement then how we add a dynamic import? Actually we can lazy load our auto imported components by simply prefixing the component with the word Lazy. Lets see how it works.

<LazyPlanetsList />. // in the index page

On our home page let's add a button that when clicked will set show to true. We don't want the list to show unless the user clicks the button.

<button @click="showPlanets">Show Planets</button>

We then need a method that changes our data property of true to be false

<script>
export default {
  data() {
    return {
      show: false,
    }
  },
  methods: {
    showPlanets() {
      this.show = true
    },
  },
}
</script>

Now we can add a v-if=show to our LazyPlanetsList component it will only show if we click our button.

<div v-if="show">
        <LazyPlanetsList />
      </div>

Lets test it out. As you can see have no list of planets. Let's open our network tab and we should see in here our planets.js only when we click the button. And there you see it. This means our planets component is lazy loaded, only loaded when and if it is needed.

So as you can see with auto imported components we don't need to write any kind of dynamic import statements, you just need to prefix your component with the word lazy. Very cool.

Explorers

your progress

710