How to use vue-lazyload properly with nuxt?
Nuxt uses ~assets
syntax or require('...')
method to implement image urls. This means that these two variants both loading images BEFORE vue-lazyload starting its work.
After images all are requested and downloaded by browser vue-lazyload know their urls and start to show them lazily. But it is already make no sense((
How to use vue-lazyload with nuxt or how avoid ~assets
or require(...)
preloading?
a simple way you can put those image to /static/img folder
that will working ...
I tried vue-loader will not require data-srcset='image.jpg'
, even sometimes I want require image background in html template ( style attribute )
another way ....
maybe can make a webpack plugin to change src='image.jpg' to data-src='image.jpg' ( or data-srcset ) after vue-loader reqire image ....
obviously I do not understand how to create a plugin ...
so , I put image to static folder ( or CDN ) when I need the pic lazyload ...
@ausir0726 Thank you. I'll try your way.
There are several advantages when using webpack's import
/require
from ~/assets
directory, such as adding hash to the filename to enable long term caching, passing images through custom webpack loaders, etc.
Therefore, I suggest not putting all images in ~/static
directory, and to answer the original question: just use require
inside v-bind with data-src
!
For example
use v-bind
<img v-bind:data-src="require('~/assets/images/foo.png')">
or :short-hand
<img :data-src="require('~/assets/images/bar.jpg')">
Because of url-loader
, require will return a url.
It doesn't work for me. I have tried both at assets
and static
directories.
Static:
<img v-bind:data-src="require('/lucky-barber.png')">
throws:
Cannot find module "/lucky-barber.png"
Assets:
<img v-bind:data-src="require('~/assets/ucky-barber.png')">
It doesn't throw error but it doesn't load the images. The img el in devTools is:
data-src="/_nuxt/img/lucky-barber.74353ad.png"
I'm using:
"nuxt": "^1.4.0",
"vue-lazyload": "^1.2.3",
and I load the plugin at:
plugins/vue-lazyload.js
with
import Vue from 'vue';
import VueLazyload from 'vue-lazyload';
Vue.use(VueLazyload);
and in nuxt.config.js
:
plugins: [ {src: '~/plugins/vue-lazyload', ssr: false}]
I have also tried adding this at nuxt.config.js
under build
and in extend
:
const vueLoader = config.module.rules.find((rule) => rule.loader === 'vue-loader')
vueLoader.options.transformToRequire['img'] = ['src', 'data-src'];
Next question will be, how to do this in a for loop that renders components with images. Without lazyloading that was: <img v-bind="{src: imgUrl}" >
Worked for me:
~/plugins/vue-lazyload.js:
import Vue from 'vue';
import VueLazyload from 'vue-lazyload';
Vue.use(VueLazyload);
nuxt.config.js:
...
plugins: [
{ src: '~/plugins/vue-lazyload', ssr: false }
]
...
.vue:
...
<img v-lazy="imageurl" />
...
Where imageurl - bound url from static folder (something like http://domain.com/img.jpg).
@coolemur I don't understand what do you mean with bound url. Let's say we have the image: ./static/example.png
? How would you write the <img>
el exactly? Note that it has to work with both yarn dev
and yarn generate
of course
@stavros-liaskos
try this:
<img v-lazy="require('./path/to/img.png')" />
this works in both yarn dev
and yarn generate
NOTE: for the path you're entering, it's a relative path.
for example:
src/
components/
App.vue
assets/
images/
example.png
// App.vue
<img v-lazy="require('../assets/images/example.png')" />
// or use nuxt alias
<img v-lazy="require('~/assets/images/example.png')" />
@stavros-liaskos
It doesn't work for me. I have tried both at assets and static directories.
Because in your example:
<img v-bind:data-src="require('/lucky-barber.png')">
You start the require from /
, which is your system root! (super weird isn't it?)
you have to start the path with ./
for current folder; or ../
for the parent folder, etc.
@DaxChen It worked, now. As you can see on my first post, I have tried that before but I've got no idea why it failed.
The only thing left to answer from my first post then, is how to do that over a v-for
loop. Let's say a parent renders children and passes to themimgUrl: '~/assets/images/example.png'
.
Parent template:
<foto-frame v-for="(foto, index) in fotos" v-if="fotos.length" v-bind:imgUrl="foto.imgUrl"/>
Foto-frame template:
<!--static works-->
<img v-lazy="require('~/assets/images/example.png')"/>
But dynamicly? I've tried this among others but with no success.
<!--Throws error: Cannot find module '~/assets/images/example.png'. -->
<img v-lazy="require(`${imgUrl}`)"/>
UPDATE:
I don't even know if it is technically possible to do the above with images located in /assets
. So, I've just moved them to /static
and load them like that:
<img v-lazy="require(`${imgUrl}`)"/>
where imgUrl
= example.png
+++ I've got lazyload working
--- I don't have the benefits webpack provide (i.e: I have to compress them beforehand)
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
There are several advantages when using webpack's
import
/require
from~/assets
directory, such as adding hash to the filename to enable long term caching, passing images through custom webpack loaders, etc.Therefore, I suggest not putting all images in
~/static
directory, and to answer the original question: just userequire
inside v-bind withdata-src
!For example
Because of
url-loader
, require will return a url.