Search code examples
javascripthtmlvue.jsvuejs2http-status-code-404

VueJs dynamically loading src not working


I am trying to dynamically load a VueJs image so that I can change it later but I keep getting a "404 not found" error.

Here is the img tag

<img class="image" :src="imageSrc" alt="image">

and the js code.

export default {
  data () {
    return {
      imageSrc: '@/assets/gallery/images/20211005_0044.jpg'
    }
}

If I put that same path directly into the img like this, it does work so the image does exist. I have also tried using ref and changing the src like that and then at first the image will load (with the path directly in the src) but as soon as I tried to change it I would get a 404 not found error back.

Note: I have seen this question Vuejs image src dynamic load doesn't work but that did not help either.

Thanks.


Solution

  • Note: this entire answer uses require to solve the problem. I know of no workarounds that avoid explicit import utilities.


    There are a couple of Vue/Webpack quirks at play here.

    First, Webpack only knows how to convert a certain limited set of import path specifications into appropriate URLs in the final build. Using a data variable as the value of a :src prop is not a supported syntax: Webpack just sees that as a generic variable and will not transform it.

    As mentioned in the question linked above, a first step to resolving the issue is using the require() syntax like so:

    <img class="image" :src="imageSrc" alt="image">
    
    export default {
      data () {
        return {
          imageSrc: require('@/assets/gallery/images/20211005_0044.jpg')
        }
      }
    }
    

    However, there is an additional quirk when the path in require needs to be dynamic. According to this answer, Webpack cannot import the file if its name is completely given as a variable. In other words, require(this.imageSrc) (where imageSrc is a string variable) will not work.

    A workaround is to only include a subdirectory (or filename) in a variable, and use a static prefix in a string, like so:

    <img class="image" :src="imageSrc" alt="image">
    
    export default {
      data () {
        return {
          imageName: '20211005_0044.jpg'
        }
      },
      computed: {
        imageSrc () {
          return require(`@/assets/gallery/images/${this.imageName}`);
        }
      }
    }