diceline-chartmagnifiermouse-upquestion-marktwitter-whiteTwitter_Logo_Blue

Today I Learned

How to add dynamic images in NuxtJS & VueJS

Let's say you have a simple component in NuxtJS and VueJS, a static image for a blog post.

<template>
  <article class="post__image">
    <img class="image" src="~/assets/images/imageName.jpg" alt="post picture">
  </article>
</template>

Simple enough, right? But you don't want to have the same image for every blog post, so maybe you're trying to add it dynamically, getting the image name through a prop and using Vue's v-bind directive, like so:

<template>
  <article class="post__image">
    <img class="image" :src="`~/assets/images/${imageName}.jpg`" :alt="`${imageName} picture`">
  </article>
</template>

<script>
export default {
  name: 'PostImage',
  props: {
    imageName: String
  },
}
</script>

And then you notice that that doesn't work. But why? The vue syntax is correct, so what's the problem? Well, there's something else at play here.

Behind the scenes, webpack replaces the image path with a module request at build time. That's fine for static images, because their paths are known at build time, but for dynamic images it's a different story, as webpack can't know what their paths will evaluate to at run time, so that won't work.

The solution is to make a module request for the images, so that webpack can work its magic on them before loading them on the page. That's done by using require(...), with the correct image path.

So your images will have to be loaded like this:

<img 
    class="image" 
    :src="require(`~/assets/images/${this.imageName}.jpg`)" 
    :alt="`${imageName} picture`"
>

You could also clean that up a bit, and extract the require part into a computed property, for better readability:

<template>
  <article class="post__image">
    <img class="image" :src="imageSource" :alt="`${imageName} picture`">
  </article>
</template>

<script>
export default {
  name: 'PostWithImage',
  props: {
    imageName: String
  },
  computed: {
    imageSource() {
      return require(`~/assets/images/${this.imageName}.jpg`)
    },
  }
}
</script>

vue-cli-service environment variables

While you can find detailed information in the official docs, I dare to spoil the fun for you:

1. All app variables are pulled in if they are prefixed with VUE_APP_.

Example: VUE_APP_API_URL.

You can now access the variables in your application like this: process.env.APP_URL.

2. All e2e variables are fetched if they are prefixed withCYPRESS_.

Example: CYPRESS_APP_URL.

You can now access the variables in your tests like this: Cypress.env('APP_URL').

Loop through a list of VueJS components

Ever wondered how you can loop through a list of VueJS components?

Let's say you have an array of components and you want to render them dynamically:

data() {
    return {
        components: ['ComponentOne', 'ComponentTwo', 'ComponentThree']       
    }
}

It's simple. We just need to use vue's dynamic component.

###Let's see how:

<ul>
    <li v-for="component, index in components" :key="index">
        <component :is="component"></component>
    </li>
</ul>

Just make sure to register all the used components where you need them.