Skip to main content

← All videos

Lazy Loading Images with Prismic and Vue.js

May 22, 2020
Tim BenniksComposable architectureCMSContent opsPerformanceFrontend

In this video I explain how I managed to add lazy loading images in Vue.js while getting image data from the headless CMS Prismic.

In this case it’s not just a matter of creating a Vue component as I also get images rendered in HTML from the Prismic Rich text field.

This is a lazy loading solution for images that works both in vanilla JS and Vue.

See it in action here: http://timbenniks.nl Find the code here: https://github.com/timbenniks/timbenniks2020

Follow me here: Website: https://timbenniks.nl/ Twitter: https://twitter.com/timbenniks Github: https://github.com/timbenniks

#vuejs #prismic #lazyloading

Transcript

what is up welcome back to the channel in this video I'll be going over how to lazy load your images when you get your data from press make and your front end is some sort of a few GS front end in my case I'm using grits um but I'm not using the grits um G image tag I'm using my own and I've done this because of the way pris make represents the data to me and because of some super fancy features they have that doesn't really work with the grits um image tag so without further ado let's go into a simple script that is usable in few years or outside refugees that's an important part and let's see how I did it no this is not a sponsored video all right let's kick this off so let's start by looking at my website itself to see how the lazy learning is working so when I go to this page you see that the first four images just loaded in with a little animation and they are here in them in the network tab so when I scroll down you'll see more loading in they all have some fun animations because why not right so every time I scroll past something that has an image it loads it in if I don't scroll there or not close to it it will just not load it so let's have a look how I did it so as you can see this here is my is this is a videos page here I have this lazy image tag I'm using a few Gs component here that wraps some native JavaScript to load those images the native way like more vanilla more old-school and I'm doing this because of how prissmann is giving me the data because Priss make em let's just before diving in here I'll show you how prism it gives me this information for some of the images as of all so that that explains why I did it this way when I go to prison ik this is one of my blog posts this is basically one big rich text alright and in my rich text you see I added an image and I added another image and what this does will just show you here there's that image and then there is another image and you see the lazy load but so what Brissac does it represents that whole rich text area in JSON objects so this header is a JSON object this is a paragraph is a JSON object this is an image it's a JSON object and then what that does once it goes into grid 'some it uses something called an HTML serializer and this HTML serializer grab that JSON from the field and converts it into HTML but the moment you do that there is no runtime few GS so I could actually not add my lazy image furious components because few GS was rendered before and I just add something in and it just wouldn't know that it existed because that's the nature of how great some works so what it does I actually or I I make my custom HTML serialization for this and I create my own image tag and then I have to add attach vanilla JavaScript to lazy load those images so that's why I chose to have my core as vanilla and a massive refugee dress or few GS around it so let's dive into how that few GS component works and I'll go over the most important props but not all of them because it will it's this video is just about the lazy loading part not about how you do responsive images that's a whole different story so really important for lazy images is actually the ratio 16 by 9 because I'm saying this like well in my case this image is sixteen by nine right but if the image is not loaded yet you need to know I'm using this CSS trick to use sixteen by nine and actually create a little box around the image that has space that takes its space before the image is loaded in because if you don't do that if you don't use that CSS hack actually if the image is not there it doesn't take space so the moment it loads in it shifts your whole interface and it just looks super bad um I know Chrome just came out with this ratio option in CSS but it's not for all browsers yet so I left it out for here so ratio alt URL and then we have widths and sizes widths is a prop that I'm using for concatenating the source set I'll get there in a sec how that works we're gonna don't we won't go too deep but I'll show you and then we have sizes which is the normal thing in responsive images so let's have a look at that lazy image dot view so let's start by the template and then we go into the scripts and then I'll go into the heart of how the lazy loading works a little bit after and you'll see that as actually the vanilla code first of all my first image tag here is V if native LaCie supported because native lazy loadings is starting to be supported in a lot of browsers now so why not right so if this is true I'll show you what that test is in a second if it's true I bypass all of the code you just saw and I'm just literally adding little loading is lazy the source yet I still can catenate I'll show you that in a bit and I've had to do a little trick to add the width and the height because if you say loading equals lazy and you don't give a width and height the browser will not know about that ratio that we just discussed so it cannot actually work because it also needs to keep space for that image tag right so if you give width and height um it can calculate that ratio and then it works um normally when I don't have loading equals lazy because my I'm using the normal old-school images that ratio is set by my own CSS so the only thing you'll have to do is like in my case I took that ratio that I give anyway sixteen by nine and I grab that ratio for the width which is the first number and then I just multiplied by ten so in this case my width and height are 160 by ninety and it's just for ratio and if it's below ten it doesn't work so I cannot add sixteen by nine this is just in the HTML spec so that's basically we're not going to look into this one now because if I do this none of the other code is executed so this is the more important one so as you can see I'm not just using source set and not just using sizes but I'm saying data - um so this is where the vanilla JavaScript comes in a little bit so I'm basically utilizing the HTML to keep state of my source at my sizes and then the moment the image is intersecting with the window so when I want to load it I remove the data - add the normal source at property and because of that the browser will just say hey I know what dude that let me just load it um if this was purely a few GS component or a react component for that matter I would have done it pretty differently right you can keep state in the few GS component itself have a data function you can do a lot of cool things there but this is kind of a wrapper around it so I wanted to keep it the same as in the other place from the Priss make output of the HTML I'll show you that in a second so you can understand what what I mean by that and okay let's go over the props of this component first and then we'll go over the image tools that I've written to make it all work so basically we have the ratio we discussed of course we have an alt we have a URL we have sizes widths if we just said this is to create the the source set then I have caption and this is just a little boolean because what I'm using normally is a figure and a thick caption so if caption is true I just put the alt as a caption and that looks like this there's a little caption here and it's just nice for accessibility right a little caption here let's see what else yes then we have the pre load and this is actually a pretty important one what I do I use this pre load it can be in this case it's just an empty pixel that I use but it can also be potentially a blurry version of your image so this is like your fallback so the normal source of the image is actually preload which is in my case just an empty gif a pixel for you it can be something else and so this is to make the browser thing when there is no source at and no sizes that this is the image so it doesn't give you any errors because in let's say Internet Explorer before it became chromium it actually would show you that like let broken image thing on the top left of your image so this is to make sure you don't get that error but it's also a nice feature because potentially you have a super low quality blurry version of your image that you can put there and then the moment the source that comes in you can actually see the new image okay so as you can see I'm mounted I load my images and there's a couple of smaller helper functions to create the source set but you see those functions they actually come from an import here so let's have a look at my image tools so image tools is is used all over my website so it's in the few component but it's also when I render the rich text of Priss Mick when I just get HTML and I still need to lazy load the images so this is the heart of lazy loading and as you can see this is not very few GS like this is like completely native like I look at the document I get all the images that are image with the clause lazy but not lazy done this is the lazy loading has been done I add this class then I don't want them because I'm attaching an intersection observer to each image I don't want to double that so that's why we have this we'll get to set image in a second so I find all images on the page I loop over them and if intersection observer is in the window if it exists I will attach an observer to that image and if it starts to intersect with my window it will say hey if it's intersecting let me just set my image and then an absorb so unabsorbed means once it's loaded I will never check it again and then if I do not have intersection observer like in I think in Safari at the moment and some older II's I will just load the image immediately I don't really care this is such a small percentage of my users so set image is very old-school but it works really well so if that image actually has lazy done attached it won't do anything but if it doesn't what it will do is we will set the source out of this image based on that data source set that it used to have and the same with sizes so it basically sets it takes the data property and adds the normal property and then it adds lazy done so I'm kind of using the state of those classes to see if something has happened and the nice benefit is also that I attach a couple of fancy animations for the images on that lazy and lazy class here so this is all you need to have lazy loading images across the board it's pretty easy then let's check this one so native lazy support and currently I set it to false because I want to show you my code but if I don't have that then it's this so if loading is in HTML element prototype it means your browser actually understands lazy loading natively and in my case it will basically kill off all this code and it will just use the loading equals lazy but let's keep it like this for now because otherwise I cannot show you and then here I have to get source set so this is a combination of the base URL of the image and the sizes array we saw earlier which is here so the URL that's the base URL of the image and this is my widths so what I want my source had to look like is that image based on a certain size with 300 W behind it right that's how source sets work so let's have a quick look at this or set for example so this source that is the image URL and then 300 W behind it comma separated so now comes the magic of Prisma because fresh make gives us image IX which is a software-as-a-service that is similar to cloud an airy for example that will render different sizes of your images and optimize them in a really good way so what I have have one URL of my image which looks like this image for example and I want to render it in 300 400 500 600 and 680 so there's a bunch of versions of that image so the only thing I have to do in image IX is say this is my base URL of the image and then I add the W for width and that's the same as that size that you see here and then of course to make sure that the source that is working we add size W comma behind it so now you would see base URL and width is 300 space 300w and then I always just rendered this but I don't want the latest coma so I'm slicing did the string and then I'm removing this last variable of the last comma I mean because when you leave that comma in it just doesn't work um thank you HTML so having Chris make it's amazing because it gives you this image IX thing and let me just really quickly show you what that is like so this image here this is my base URL press make ads auto compress and format for you so compress is to do like some automated quality optimization and format is to say hey you have Chrome let me render you web P and then I add the W for width so I can add 680 oh now it's the original because it's not a correct number that's 680 or if I don't add a width it's the original size so I can make different versions of this image just by appending something to the URL for you if you don't have image IX it will be different but if you have press make you get it for free so make sure you use it and actually that's kind of it for the few Gs component here so now let's have a look as to why is it actually when why do I use this native code right so here is this HTML serializer we spoke about before so what this does is when press make renders the HTML from your rich text component it actually gets a whole chunk of JSON that represents that text area and in my case if the type of thing is rendering is an image I say okay I'm gonna overtake what you do natively yourself I'm gonna write my HTML so in this case this really looks like that few GS thing and was just rendering right so I actually have data source set and there's like a figure and there's a fake caption so here you can see there's my figure there's my aspect ratio that we just spoke about but it just get the original width and height Priss make then I check if it's native Laci supported and I use source at if not data source at and then here's the get source said you were a function we just discussed with the base URL and decisis and then here I just had I'd kind of hard code my sizes property here because you know for my block it's always the same it's always here it's always looked like this so the size is they change like that it's always the same and then my alt my title SEO tools have started to complain that it didn't have titles or I added it then my default source that is in this case this empty pixel then if native loti native lacey is not supported I add my lazy clause so I start I can actually lazy load and then this width and height and of course the fake caption and in this case I know I wanted so I just added in so I overrule and the HTML press make would normally render for me by doing my own and then because of that Lacey class my code can actually start lazy loading this thing and I'm doing that with a little mixing and it's super simple like when it's mounted on the next stick actually lazy load my images that's the lazy loading function that we just looked at and this is how I use that so when I go to my writing templates like this is my blog post page right so you don't see much I don't let me just there we go so actually this is my blog post content this is the rich text we just saw and then here I have a little mix in for images so basically when mounted because my mixing works on mounted it will actually fire the load images from image tools so image tools is here load images so basically unmounted of my blog post it will try to find the image dot lazy and then lazy load it because that HTML exists so it works so that's a became a pretty long video but it actually explains how to integrate the press make images in few GS and natively and it's also if you wanted to you can extract just the few GS component from this and use it in other places I guess that's it so thank you for watching and if you like this type of video where I actually show some code please leave a like and put something in the comments so I can maybe do more of it okay thank you bye bye