I need an advise please,
I'm still stuck after trying in a lot of ways to create a reusable picture element component supporting native lazyload with a fallback to Lazysizes.js library and accepting variable number of image source types and dimensions (in <source>
and his srcset
attribute).
To achieve this I was looking to use multiple require
in a computed method and these need to be concatenated before being returned form the method (because I need to require
for every available images dimensions) but I hurted again to what I think is a require
limitation.
The img dependancy isn't found because I think require
aren't resolved as I was presuming. here's my code to help you understand:
// parent component
<picture-elem
:name="`${img}`"
:img-alt="`${alt}`"
:formats="['webp','jpg']"
:sizes="[['512x768', '2x'], ['256x384', '1x']]"
:img-class="'product-img'"
:lazy="lazyloadImg" //true of false depending the context
/>
//in PictureElem component <template>
<picture>
<source
v-if="formats.indexOf('webp') != -1"
:srcset="(!lazy) ? srcsetWebp : false"
:data-srcset="(lazy && !loadingAttrSupport) ? srcsetWebp : false"
type="image/webp"
>
... // other sources element for every accepted image types
<img ... //fallback img
</picture>
//in script > computed methods, an example of the problematic part with webp
computed: {
getSizesLength () {
return this.sizes.length
},
srcsetWebp () {
let srcset = ""
//loop through the array of availaible images srcset sizes
for (let i = 0; i < this.getSizesLength; i++) {
// require ( [path] + [base name] + [dimension] + [targeted resolution or screen width]
srcset += `${require(`@/assets/img/${this.name}-${this.sizes[i][0]}.webp`)} ${this.sizes[i][1]}`
// if there is following sizes, add a comma (,)
if (i < (this.getSizesLength - 1)) {
srcset += ", "
}
}
return srcset
}
I always get with it:
Failed to compile with 1 errors
This dependency was not found:
* @/assets/img/img-name.webp in ./node_modules/babel-loader/lib??ref--2-0!./node_modules/vue-loader/lib??vue-loader-options!./components/PictureElem.vue?vue&type=script&lang=js&
I tried also with "~/assets/img/.."
I guest the problem is with the concatenated require
as my debugging checks confirmed me.
I also know that a regular
return `${require(`@/assets/img/${this.baseName}_480.jpg`)} 480w, ${require(`@/assets/img/${this.baseName}_800.jpg`)} 800w`
should work as explained here by Alexander Lichter: https://blog.lichter.io/posts/dynamic-images-vue-nuxt/#bonus---using-srcset
This wasn't my first way and I tried different path inspired by my findings in many articles. This was my last hope to get all the flexibility and enough dryness I planned for this component...
I will try with a <slot>
to define the exact require
s in the component parent but I would really like to learn if is there a way to achieve what I wanted in the way I was trying or confirming that required
can't be use in this way (concatenated).
Thank you in advance for your time
I finally found that my problem was elsewhere, a part that isn't showed in the question to simplify the comprehension but I discovered you can't
require
with string variable in the beginning of the path. I was calling like this:but it seems
require
can't resolve the path like this. Adding the path fixed the problem:And watch out if you forget to write the complete path (like missing the
/img/
part) becauserequire
will try to get all files in the assets and will output an error for every assets like fonts files or any other that doesn't fit for vue-loader aka webpack loader (I think so).