responsive-loader
responsive-loader copied to clipboard
How to reference different sizes in a template
Responsive-loader is generating all my images beautifully with the correct names and sizes, but I can't figure out how to reference other sizes than the default (smallest one) in my template!
// webpack.config file
...
{
test: /\.(jpe?g|png)$/i,
loader: 'responsive-loader',
options: {
adapter: require('responsive-loader/sharp'),
sizes: [600, 1200],
placeholder: true,
placeholderSize: 50,
name: '/assets/img/[hash]-[width].[ext]'
}
},
...
And this is how I'm referencing the images in my template html
<img src="${require('./assets/img/image_0.jpg')}" alt="">
This gives me the 600px wide image and I would like to get different images based on screen size. Any pointers?
@bparticle – do
<script>
const responsiveImage = require( './assets/img/image_0.jpg');
</script>
And then use in your HTML
<img src={responsiveImage.src} srcset={responsiveImage.srcSet} alt="">
And your srcSet will be set up.
@Melzmr Thanks for your reply! Your answer makes perfect sense, and it is one of the options out of many I tried, but somehow nothing works. I'm still scratching my head over this but can't let it go. I'm using Vue.js at the moment and this is the code I'm currently testing:
<template>
<div id="app">
<h1>{{ greeting }}</h1>
<p>{{srcTest}}</p>
<p>{{src}}</p>
<p>{{srcSet}}</p>
<img :src="src">
<br>
</div>
</template>
<script>
const responsiveImage = require("./assets/img/image_0.jpg");
export default {
name: "app",
data: function() {
return {
greeting: "Hello",
srcTest: responsiveImage,
src: responsiveImage.src,
srcSet: responsiveImage.srcSet
};
}
};
</script>
The only positive response I get is the raw responsiveImage reference in the first <p> tag. It's outputting the base64 code that is supposed to contain the image (data:image/jpeg;base64,bW9kdWxlLmV4cG9ydH......). If I put this in the image tag however I get a broken image link. The other tests aren't outputting anything at all (responsiveImage.src and .srcSet).
@bparticle looks like you have another loader hijacking your image (probably url-loader
?) …
@herrstucki That will be the case probably. I think the way vue-cli is implementing its webpack configuration is awkward to say the least. I tried to set it up like this:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// vue.config.js
module.exports = {
chainWebpack: config => {
config.module
.rule('images')
.use('responsive-loader')
.loader('responsive-loader')
.options({
adapter: require('responsive-loader/sharp'),
sizes: [600, 1200],
placeholder: true,
placeholderSize: 50,
name: '/assets/img/[hash]-[width].[ext]'
});
},
configureWebpack: {
plugins: [
new BundleAnalyzerPlugin()
]
}
}
But the trouble with that setup is not immediately relevant to this repository I suppose!
I found the issue (and it cost me many hours so I hope this may help anyone in the same situation). My images were not displayed due to the preceding slash that I put in the responsive-loader configuration (see previous code example). Also I changed the way I implement the loader in the vue-cli setup. This setup has fixed my problem:
// vue.config.js
module.exports = {
chainWebpack: config => {
const imgRule = config.module.rule('images');
imgRule.uses.clear();
imgRule
.use('responsive-loader')
.loader('responsive-loader')
.options({
adapter: require('responsive-loader/sharp'),
sizes: [600, 1200],
placeholder: true,
placeholderSize: 50,
name: 'assets/img/[hash]-[width].[ext]'
});
}
}
So name: 'assets/img/[hash]-[width].[ext]' instead of name: '/assets/img/[hash]-[width].[ext]'. This is not a vue-cli specific fix so I think it is useful to post back my solution.
For other templates using html-loader
this can be accomplished by using multiple source
elements. Here's a pug example:
picture
source(media='(min-width: 1024px)', srcset=`${src}?size=1280`)
source(media='(min-width: 768px)', srcset=`${src}?size=1024`)
source(media='(min-width: 640px)', srcset=`${src}?size=768`)
source(media='(min-width: 481px)', srcset=`${src}?size=640`)
img(src=`${src}?size=481`, loading='lazy', alt=alt)
Multiple source
elements are required in this case since html-loader won't transform a single srcset with multiple target resolutions.