I am trying to use responsive-loader in my vue/node project, but it only returns a data url.
I installed with
npm install responsive-loader sharp --save-dev
Here is my vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('responsive')
.test(/\.(jpe?g|png|webp)$/i)
.use('responsive-loader')
.loader('responsive-loader')
.tap(() => {
return {
adapter: require('responsive-loader/sharp'),
}
})
},
}
In one of my components I have
let responsiveImage = require('../assets/image.jpg')
console.log(responsiveImage)
And the output of the log statement is this data url image of a small white square:
data:image/jpeg;base64,bW9kdWxlLmV4cG9ydHMgPSB7CiAgICAgICAgICBzcmNTZXQ6IF9fd2VicGFja19wdWJsaWNfcGF0aF9fICsgIjNiOTFlYjAwY2E1OGU0MTkzMGY5OGY5ZGZkMDc3YTVmLTc4MC5qcGciKyIgNzgwdyIsCiAgICAgICAgICBpbWFnZXM6WyB7cGF0aDogX193ZWJwYWNrX3B1YmxpY19wYXRoX18gKyAiM2I5MWViMDBjYTU4ZTQxOTMwZjk4ZjlkZmQwNzdhNWYtNzgwLmpwZyIsd2lkdGg6IDc4MCxoZWlnaHQ6IDEwOTd9XSwKICAgICAgICAgIHNyYzogX193ZWJwYWNrX3B1YmxpY19wYXRoX18gKyAiM2I5MWViMDBjYTU4ZTQxOTMwZjk4ZjlkZmQwNzdhNWYtNzgwLmpwZyIsCiAgICAgICAgICB0b1N0cmluZzpmdW5jdGlvbigpe3JldHVybiBfX3dlYnBhY2tfcHVibGljX3BhdGhfXyArICIzYjkxZWIwMGNhNThlNDE5MzBmOThmOWRmZDA3N2E1Zi03ODAuanBnIn0sCiAgICAgICAgICAKICAgICAgICAgIHdpZHRoOiA3ODAsCiAgICAgICAgICBoZWlnaHQ6IDEwOTcKICAgICAgICB9)
I expected it to be an object with src
and a few other porperties.
Why isn't it loading my image?
The problem was (as mentioned my Michael Levy) that my rule was never reached because an existing rule for all images came first. To fix this, I added .before('images')
to my rule, so it would check my rule first.
One other issue was that for some reason npm
had changed my vue-cli
to version 3.x without me noticing. Because of this, I was getting an error that .before()
was not a function. After running vue upgrade
, and changing to version 4.x, it started working.
I also added .resourceQuery(/srcset/)
so it would only affect images I specifically wanted it to.
My new vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('responsive')
.before('images')
.test(/\.(jpe?g|png|webp)$/i)
// if the import url looks like "some.png?srcset..."
.resourceQuery(/srcset/)
.use('responsive-loader')
.loader('responsive-loader')
.tap(() => {
return {
adapter: require('responsive-loader/sharp'),
}
})
},
}
You are adding new rule for images but projects generated/managed by Vue CLI already have rule for images and this rule has a precedence as it is added 1st
You can find the default rule by looking at the code or by running vue inspect
command and checking the output.
Here is the documentation on how to remove the original images
rule