A tool built for generating multiple image sizes for various devices resolutions. Written to take advantage of scrset properties of images on webpages without requiring a third party service to process them or host them directly. The main advantage is reduced image size for smaller resolution devices allowing faster load times and saving bandwidth.
Links
Why
Other than the bandwidth reduction, it was also done in mind with reducing developer overhead for boiler plate code that is required to take advantage it. The complete solution involved using vuejs component to generate all image properties based on the reference of the original image. The data would be pulled from the vuex store which in turn pulled the data from a REST API service based on what page was loaded.
The generator tool works by mirroring an original image folder and replacing the original with various sizes in the mirrored version. It then outputs two CSV files with the details of the files generated. Originally made with a database in mind so these files could be directly imported. It would then be exposed via a REST API referenced by the originals file name. This worked great for dealing with things like multiple items/products.
The main disadvantage to doing it this way was that an API call would be required to pull the images and if that took too long. It some cases it seemed like the it would be faster just loading a one off image not optimised. One way around it was to pre-load a selection of common images on the first page load into the vuex store, even some popular pages so when those specific pages would be hit, it would be near instant as if the page was perfectly statically generated for that device.
Usage
Checkout the readme on Github for details. Includes generating images and information the resulting CSV files, plus example SQL queries.
Frontend implementation
Here is a quick example on how to implement the results of the tool on the frontend.
The vue frontend would do an API call and pull all the image information required for the page. The component would then use that data to generate a perfectly sized image for the device. I also used the vue-lazyload component to indicate a loading image on a slow internet connection.
Note: If there are not many images yet on the website. A good trick is to have the vuex store pre-filled so an API call isn’t needed and the load time is even faster.
Single image by ID
<img :data-srcset="images[id].srcset" sizes="(min-width: 650px) 400px, 100vw" v-lazy="images[id].url" :alt="images[id].description" style="width:100%">
Multiple images based on a product
<div v-if="images && product.imageids && images[product.imageids[0]]">
<img v-lazy="images[product.imageids[0]].url" :data-srcset="images[product.imageids[0]].srcset" sizes="(min-width: 650px) 300px, 100vw" :alt="images[product.imageids[0]].description" style="width:100%">
</div>
Vuex data structure
{ "image_id": {
"id": "image_id",
"url": "fallback/image_url.jpg/"
"srcset": "generated_src_sets"
"description": "alt text description if needed"
}
}
Tech
- Nodejs plus mainly these npm packages:
- Imagin
- Sharp
- Vuejs for frontend implementation (Optional)