Search code examples
vue.jswebpackvue-cliresponsive-imagesresponsive-loader

responsive-loader only returns a data url


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?

Update

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'),
                }
            })
    },
}

Solution

  • 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