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.
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}`);
}
}
}