 Okay welcome everyone thanks for coming along this is the first time I've done a in-person presentation in four years so bear with me I'm gonna start by getting a show of hands who here's been to a conference session where they started it by asking for a show of hands I'm not gonna do that so what we are gonna do is we're gonna have an overview we're gonna talk about what CWVs are we're gonna talk about how to improve them with Drew and that's it now a bit of a warning there's some TLA's ahead or three letter acronyms and there's lots of them but knowing what they mean and how they apply to call with vitals they're what I consider table stakes entry for a web industry professional such as ourselves so I think they're important for you to know them so if you scan this and you head to there there's a bingo table and yep I'll give you TLA for free if you get five shout out you might win a great prize this game of the prizes may not be great so what are CWVs but more importantly why should I care well it stands for core web vitals for those playing bingo and it's a series of measures that quantify the basically the user experience and the quality of life for your users as Ricky said in her session you've all visited a site where it took forever to load and you know you just to give up and abandon it and you know this is about trying to improve that experience for the users so there's quite a few studies that show improving these lead to improvements in your business outcomes one such study is from Vodafone that showed improving the CWVs by 31% directly led to an 8% increase in their sales and there's a heap more studies there if you head to that URL but basically CWVs are made up of three core measures so let's meet them the first one is LCP and for those playing bingo this stands for largest contentful paint it's a measure of when the URL sorry when the user sees the browser is basically finished and the largest piece of content has been rendered it's measured in seconds and anything under two and a half seconds is good and anything over four is poor and actually this is where we'll spend most of our time in the session because the other two measures Drupal doesn't really struggle with just by nature of how it's built but this one you can't hit grief with the next one is FID which is first input delay and this is how long does it take from when the page is loaded to when our interactivity starts to occur so you can click you can scroll you can fill in forms oh we've got a winner all right we've got three nostalgic prizes here you can choose from circa 2017 aquia fidget spinner I believe you a genuine copy of Mac OSX snow leopard in box or 2019 Drupal South Hobart Cup okay you want the car okay so first input delay is not such an issue with Drupal because we're doing SSR server-side rendering but for an SPA which is a single-page app if you're doing client-side rendering CSR it might take a little while for the JavaScript to rehydrate the page and for things to become interactive if you notice we're wearing these as color t-shirts that most of the printing is done on their websites a classic example of this done poorly it's a big heavy JavaScript app you click on a link it looks ready you can't actually click anything do anything for quite some time so this one's measured in milliseconds under 100 milliseconds is good and over 300 milliseconds is poor now not all tools can measure this and we're going to get to tools in a minute and some of those they will use TBT as a proxy which is total blocking time so let's make the third corporate bottle it is CLS and this one is cumulative layout shift so this is when you're about to click on something and then something else loads and pushes the page down so an alert bar or you know maybe it's a modal pops over the top and it's very annoying how I'm sure you've had it happen and it's measured in two different fractions one of those is the impact and the other one is the distance so a small element moving a small amount is a low score it's not a big deal but say the major part of the page moving a lot it is a big deal as I said it's measured by two fractions so if you take one fraction times a by another you get a smaller fraction so the numbers here are small under point one is good and over point two five is poor things to look out here look out for here like as I said banners or alerts that come in you know the cookie consent thing if that's coming in above your content pushing it down but also images that don't have a fixed height and width on them I frames as well and we'll talk a bit more about that later so there are three measures how do you go about improving them well as with everything performance-related you know measure change measure change there's a great article here about getting started and there's lots of great tools for ongoing measurement if you use a Google Chrome the browser it automatically collects data as you browse around and sends that back to PSI page speed insights and if you're a site manager you're a site owner you can log in there and look at that data from real real-world experience there's also web vitals Chrome extension so that lets you you look at it by turning the extension on and a JavaScript API for it so the browsers actually have an API for this and there's an npm package called web vitals that lets you measure this and push it off to your own monitoring system so if you're using cloud watch or something you can collect real user data but the thing we're going to talk about today is Chrome dev tools and the lighthouse report and we talk about that because it's pretty easy to get started with it and as I said before it's one of the ones that uses total blocking time because it can't measure first input delay there's also various rum tools which is real user monitoring if people still playing bingo there's no prizes left but yeah that's something like new relic that will do real user monitoring and push that back so as I said lighthouse I'm going to attempt to switch to a different browser and open up Chrome see how I go yep it's gonna work I'm just gonna go to previous next website so I'm not calling anyone out if you open up the console and you click on analyze page load and I cannot see my mouse this will run off and generate a report for you all that runs I want to talk a bit about it so we're going to focus on lighthouse because most of us here doing local development and you don't want to be making these changes in production so this gives you the ability to make some changes measure make changes measure and you know make sure you're seeing improvements that you want so looking at this here oh my mouse is back excellent down here we've got largest content for paint three seconds not ideal I'm sure if I rerun this again and the case was primed this would probably improve should have done that forehand sorry can't shift 0.02 and as I said before it uses TBT instead of first input delay because it can't measure that but as I said the main thing that Drupal's interested in or the thing we have to optimize for Drupal is that largest content for paint and so just casting your mind back that's the time it takes for the biggest piece of the page to be rendered so the page appears ready so you can filter to those things and down here it offers you some suggestions some suggestions on how to improve that we're not going to focus at those in detail just yet the thing to take home from this is it gives you this one element found it'll tell you what it considers the element to be the large just contentful paint is so for the previous next side is this large sliver text in the middle here so when you're optimizing that score you're trying to optimize for the time it takes for that piece to be rendered because in the eyes of you know the web vitals that's when the user feels like the site is loaded okay I'm gonna see if I can switch back now so once you've gone through all these steps which we're going to get to and you've got your core web virus looking good it's obviously not feasible for every time you push a change you have expected developers to run a lighthouse report and make sure they're having course of aggression so thankfully there's an NPM package for that called lighthouse CI and you can build that into your CI CD chain so you set your targets in a JSON format you say okay I want 100 for SEO 100 for accessibility and maybe you know we start at 95 for performance because that's where you could get it to every time you push a build this runs you see our job will fail if there's aggression in any of those and sometimes you know you can find what that is but sometimes it's the client's added a large piece of JavaScript and you can't do anything about it and at that point you might have to accept that okay we're going to go from 95 to 93 for a performance score and the reason this tool is great is because to make that change you have to commit it to the repo so if in three months down the time down the road you know there's an order done and your scores on 80 you can go back through the git history and say well we went from 95 to 93 when we added that feature and then 93 to 87 when we added that feature so you've got that trace ability to work out okay where did we get to where we are if you're coming out from the other side you've got a brand new project that's a brand new project if you're coming at it from the other side and you're trying to retrofit this into existing project probably start where you are and ratchet it up as you go along now I'm not going to go into detail about how to set this up it's probably a whole session on its own I hope to write a blog post about it in the coming months so keep an eye out for that on previous next website we have got recipes for running this in our CI tool of choice which is Circle but we've also had it successfully running on GitLab in GovCMS pass so it's definitely possible I don't think you can do it with SAS I'm actually pretty sure you can but perhaps it's something that GovCMS would consider adding for everyone else so before in the report you're down the bottom you saw it made some recommendations I'm going to go to those in a bit of detail here some of them are low hanging fruit and then after that we'll get into some more a little bit more complex things so the first one that will probably say is minimize the number of elements in your page found this many elements my colleague Daniel presented the session yesterday on theming with bundle classes layer builder and twig as he said in that session and Michael and his bundle classes are the best thing to come to Drupal core in well if you ask most the maintainer of the drush 10 years so have looked at that because Drupal is notorious for outputting div soup you know everything's wrapped in all the layers of divs that you'd ever want and you end up with a lot of elements in the HTML and if you think about it logically before the browser can render that largest contentful paint it has to pass the whole tree so you've got less elements it's gonna be more performant and that techniques that Dan talked about there can help with that the next one is aggregation and the lighthouse tool is actually smart enough to work out that you're using Drupal and it'll say add the advanced aggregation module now this is degrees of adding it I would say if you're starting a new project add it from day one and that's without everything I'm at it measure it you know configure it measure it there's a lot of options and it's not just a matter of turning it on and so you need to tune it to what's right for your site on the converse if you retrofitting this to an existing site you need to be wary of things that might break you're completely changing the way JavaScript and CSS are aggregated things might appear in in the dominant different order like the order that the CSS or JavaScript come in might vary so you probably want to do some testing to make sure you haven't broken anything and tweak the settings this one's probably obvious bit of a no-brainer image sizes so it will always say to you you know make sure you're serving the best image sizes for your viewport we're lucky that we're with Drupal we have the responsive image formatter which we had for very early days of Drupal 8 and that lets you configure what image style to use for each viewport and you probably start off your project with this in a pristine condition but over time you know you need to get things out to meet deadlines and you end up reusing some image styles that may not be the best fit for that viewport one thing to definitely watch with that responsive image formatter is what you set for the fallback image you might get to the bottom go okay I'll just use the original image and I have seen sites serving you know 14 meg of images to iPhone users because the fallback is being served to the iPhone user so be wary of that there is no real easy way to do this I pretty old-school on this so I will take the design system or and look at the viewports in the theme and I'll go to each viewport and then take it down one pixel so it triggers it into the next one down and that's the maximum width that viewports going to be so I know that I need an image and I can measure the elements in the DOM right-click inspect element hover over it get the size I know okay that's the maximum size that image is going to be at that viewport write it on a piece of paper or you know notepad times a by-two for the retina version and in the end you end up with a list and I've done implor implementations of this for say like a card component which is common that it has it all different flavors as the browser gets wider you know 28 image styles just to serve that one component and obviously if you don't want RSI repetitive strain injury if you're still playing you probably want to add some automation around that and what we've been doing at previous next is we have a console command in our project that is like a wizard to help you generate image styles so you say you know PHP what if we normally have a console command for the project so might be the name of the project gen image styles and it's a wizard it'll say what's the size and what's the name and you say you know 300 by 300 you know card small and at the end it spits out the original version of those and it also does the like you can all have so have it do the retina versions and you end up with a heap of YAML files in your config export and then you run config import it's a much easier than clicking all this stuff together and I did say this was probably obvious but I'm still banging on about integers yeah there's some cumulative layout shift considerations here too so make sure that all your images and I have a width and a height on them and if you are using the responsive image format unfortunately it doesn't support that yet and there's a patch the top one of these issues and that will give you support for setting a fixed width and height on your picture element also since Drupal 9.4 most image format is now support adding a lazy attribute if you recall back to Ricky's session yesterday you can go to the formatter and you can say lazy on for any images that are below the fold and they won't be loaded until the user scrolls to there that's not supported unfortunately when you're embedding media into the WYSIWYG field but there is another issue for that which adds support for that so I have all the both of those the next thing you'll probably say is use modern image formats and in 2022 PNG and JPEG aren't the best format for the web there's two different things that I recommend web P or AVIV now there's a module for both of these because it's Drupal but the problem is and Nathan's in here telling about they both take over the same route in Drupal so the Drupal image style download controller is the thing that generates those styles and both of them say don't use the core one use mine so you have to pick one or the other and the one that you pick depends on probably on what your browser share is for your project AVIV is only supported in about 70% of browsers at the moment edge and safari notably don't support it web P is about up to 97% if you've got to support IE you can't use either but if you use the picture element in the source sets that you add for it you can have a type so you can serve web P AVIV JPEG PNG and it will pick the one that the browser will support and serve that there are some other caveats with the AVIV module credit to Nathan for finding this if you have two files with the same name the way it works is it sees incoming request it's some image dot AVIV and it looks for some image dot JPEG or some image dot PNG in the folder where all your files are but if you have two files called some image and once JPEG and once PNG the one that depicts is random yeah it's random so that's just one thing to watch the other consideration with AVIV and it look I'm I'm not talking about AVIV but it's only 70% support but the compression ratio is seriously impressive it's probably a factor of 10 better than a JPEG but the quality is dramatically better it's close to the original but the thing you have to be very obvious that not all servers will support it it's not supported in PHP until 8.2 it's not supported by cause image conversion process yet but there is an issue for that so if you do go with AVIV you probably have to do some server configuration and if you're running on machine that you that you can't control so the build process for you might not be able to add support how are we going for time I've got 10 minutes to go a bit hurry up so alright code splitting my co my colleague Ricky gave a whole session about this at Drupal South 2021 there's the link to it but what it boils down to is not sending JavaScript to users when they don't need it so now that we have IE11 is dead we can serve our JavaScript using ES modules and so we use a code bundling tool like webpack or a roll-up to generate those ES modules and if you add that type of the module attribute to your script tags yeah they're automatically deferred and async by default which is our next topic yeah so one of the key aspects of improving your LCP is getting rid of resource load delay and that's when you've got a whole heap of chain requests and the browser's sort of lining up and loading one after the other a lot of scripts when a browser encounters a script tag unless it has the async or deferred attribute on it it will pause rendering and it'll execute that script so this is an easy one to check for you know inspect the source of your page look for script tags if they don't have defer or async or they're not a module that means when the browser gets them it's going to stop and pass them and won't render until it's finished if you have some JS that does need to run early you as Ricky said yesterday inline that but make sure it's only a small amount lazy loading again Ricky had a session about this yesterday and I hopefully you saw it if not wait for the recording if you've got a view or react app that's pairing some part of your site don't load you know react on until the user interacts with that component it's pretty sounds pretty obvious when you when you think about it but yeah it's not something we've been able to do for some time because of IE this also applies to images and videos as we talked about for that lousy lazy attribute and I frames as Ricky spoke about yesterday on one thing to be really wary of is the video in bed from YouTube I think that's around about one meg of JavaScript with all the stuff that is being added by YouTube all its tracking and its interaction so whether how far you've got through the video and stuff so if you've got a video in a module that when you click the button the video pops up don't load the video don't load the JavaScript from YouTube until the moment so as Ricky said yesterday there's if you don't not not everything supports the lazy attribute on iframe like Firefox so you can use it's lazy project from triple dot org and it will do a lot of that lazy loading for you stuff like YouTube's just supported straight out of the box can erase a bit faster here optimizing fonts the first thing to probably say is to use font display swap which is a CSS property and that will show text immediately the browser will render a font that it has and then once the font's loaded it'll render the other one and I think that was one of the recommendations it had for us in our previous next site there so we can we can take that away it also should add hints to the browser that you're going to need to load fonts if they're loading an external font so you can put a link tag in your head with a rail equals preload and that'll tell the browser to fetch that font ahead of time if you don't add that it has to pass the CSS find the font family decoration get the URL and so it's kind of like it's waiting till it actually gets to that before it knows it needs to do it if you add a preload it can start fetching ahead of time one thing that is recommended nowadays is to actually download the fonts and serve them locally from your server and we're getting to real yak shaving stuff here but that extra DNS request that it needs to make to an external domain can add to that resource cascade okay so we've gotten through some of the easy stuff and there's quite a lot there if you've got this far and you're still not happy with your scores this is where things can get a little bit hairy and we're gonna get a bit technical but before I talk about that the first thing I have to address is third-party scripts this is the elephant in the room even if you get your site lean you know the marketing department is going to want a Google tag manager and that's going to download hotjar and that's going to download Facebook pixel and you know before you know it you're nicely insights loading five mega JavaScript and that's all being passed because they want to get every single interaction so it's got to be render blocking in this scenario there are a few things you can do but it it kind of depends on what version of Google that Google analytics you're using if you use in Google analytics version for party town is something you can look at any to for offloads all third party scripts to a web worker so it's running in a separate thread so in process if you're using universal Google analytics you can't use this unless you set up a proxy on the same domain as your site and you proxy all your Google analytics traffic through that and that's because Google analytics the universal Google analytics doesn't support cause so definitely this is one you have to do on your own there's no module to turn on for this there's no one-size-fits-all solution and what it boils down to is script type equals party town and then you add the party town library okay so we spoke before about render blocking JavaScript but every CSS file is render blocking and if you think about it logically it makes sense right browser's not going to start rendering then get to a CSS file and that changes the layout or the font size or the colors and then do it all again right it's trying to be efficient so if you've got a really large style sheet and you're serving at every page the browser has to pass that before it can even start rendering so if you're still using one mega you know SAS file you got stole dot CSS comes out the other side and you put them out at every page you're going to have some real pain here first step is what Ricky spoke about yesterday making sure you're using the Drupal library system to have separate CSS files for each components and only attaching those when you know the page is rendering that component that at least make sure that you're getting CSS that you need and the small files but what's recommended is that you only you take the critical CSS and the critical CSS is a CSS that's required to render the page above the fold and you inline that and you defer all other CSS now you can't do that with Drupal and you have to reach for some Node.js for that and the package to do that is called critical it's written by one of the Google Chrome team to my recollection and what it does is uses puppeteer to load up your page and it will render it and it uses Chrome DevTools to extract just CSS that's required for that part above the fold now you're probably saying well I have different things above the fold on different pages one thing we've been doing at PNX is generating multiple critical CSS files and if you think about it along template lines so you might have an article template an event template and we generate a separate CSS file for critical CSS file for each of those we're using a naming pattern like you know critical dash dash event or critical dash dash article so that brings us to the next slide this is how you actually use it with some Node.js I've heavily simplified this just for a single case but you can probably extrapolate from here how to use it for multiple you import the package you pass you fetch some URL as you fetch a URL and get the HTML from it and then you call the generate function and you tell it where you want to spit stuff out and what we can hide to analyze so the this is something that you obviously integrated to your build process you probably don't have to update it every time only if you're changing stuff that you know is going to be in that critical CSS okay we're nearly nearly there I'm going okay for time I think I am so before we spoke about preloading fonts and deferring style sheets and inlining CSS but how do you actually do that in true pool okay so one thing you do is swap out this service this is a service in core that does most of the CSS like there's the link tags that go into the head that say you know link type of style sheet and if you want to replace service just Google for you know drewable replacing service but there's an excellent blog post on our site from several years ago from a former colleague Sam Becker about using the decorator pattern for that and that's how we would recommend it when you stub that out what you're effectively get is a when you decorate that what you get is a method called render and it gets passed an array of CSS assets and each one of these is like the files that need to be added or the actual CSS and in there you have full control now the default implementation just outputs link tags in a topic style sheet with the URL so you can add pre-connect hints this tells the browser that at some point you're going to need to make a DNS look out to you know say we've got some fonts the proprietary on typekit you add a pre-connect hint and that goes into your head and the browser will see that and I'll know okay I'm going to need to make a DNS connection to there I'm going to need to make a connection to there let's do the DNS look up now you could do pre-loading it's back by that before so you've got a font you know in some point one of your CSS files is going to have that in an ad font family you say okay relic was preload go start fetching that for you before you get to the CSS you can inline the critical CSS so this is where we're taking the contents of those CSS files we're writing our implementation is a little bit more complicated we're doing theme suggestions and stuff to try and work out which folder include this is the basic implementation you know I'm using markup create there don't use that unless you know what you're doing we do know what we're doing here we know that that file is you know is safe anytime you reach for markup create your circumventing Drupal's auto escaping so just make sure you know what you're doing there and then every other CSS file we render it as deferred and so what that looks like I'm going to have to scroll here is instead of saying link type equals star sheet sorry relical style sheet we say like relic was preload so the tells the browser we're going to need to load this CSS file at some point but don't load it yet because I don't want you to slow down you've got everything you need in that inline CSS render the page and then you put the ad style as a hint for the browser and we just put this data attribute on it data style sheet swap we also have a no script version in case the user doesn't have scripts it's just the normal the fault thing you see in core and then we have some JavaScript it looks for all data style sheet swaps you know and once the page is loaded we swap it from relic was preload trailer because style sheet now this is actually the recommended way of loading CSS in 2022 if you look at the web dev docs it's a variation on it because the way they recommend isn't supported by CSP content security policy if you're still paying yeah so they recommend using inline script and if you don't have a strict content security policy you can probably not bother with this and just have an on-load attribute but you know on load is unsafe in in line for the security people out there okay so that's everything now pretty much everything I've spoken about here I gleaned from these docs they are they are very comprehensive it takes you through it from start to finish we didn't talk much about first input delay we didn't talk much about cumulative layout shift as I said they're not really a problem with Drupal most of your time will be spent optimizing for that largest contentful paint we got there I'm always around on Drupal Slack I'm always happy to answer questions about this stuff if you don't get to talk to me here find me there and yeah if you're not in the channel go ahead and join there's nearly 500 maybe 550 of us there most of the great people you meet at this conference will probably hang out there during their work day and you can keep up the connections that you've made here this week questions excellent hey max so the problem that you had with the previous next slide was the case was how often do you find that just a slow load time the pain is actually your problem and how do you fix that the previous next sites not probably no no I'm just gonna say I'm gonna clarify previous next sites a very simple site right I find it's very rare that it's just the not warned thing in fact when we do our lighthouse testing in CI we warm it with curl first to rule that out and even with a warmed and like a really content-heavy site it's very hard to get the scores up really are previous next one because there's not a lot of images above the fold and it's maintained by Ricky and Kim like they're two excellent developers like I I without any like I didn't know that site had that score I just picked it at randomly so credit to them but on that front like the session that Kim gave yesterday about scaling through the pandemic had a lot of talk about there in about case-hit ratios and make sure your cash is warm and I think if you're doing purging right which I think Nathan's site there your case lifetime is a year oh yeah huge a long time yeah so relying on the purge system in and having things cash as long as possible yeah check those sessions out if you didn't see them okay that's a lot to take in on thanks everyone for listening