Lighthouse Scores

Lighthouse can show you a lot of low-hanging fruit to improve your site's performance. It also points out ways to make your site more accessible, follow best practices, and perform better with SEO.
November 30, 2020

Performance metrics

Best practices

Performance best practices

  • CDN
  • Netlify

Image Optimization

  • Cloudinary
  • loading=lazy
  • SVG







Hello, Jeroen.
Hello, Dillon.
I think today we're going to eat our vegetables a little and instead of talking about opaque
types and fun stuff like that, we're going to talk about something that maybe not everybody
wants to talk about, but I think it's important.
I don't want to talk about vegetables.
Well, do you want to talk about lighthouse scores?
Oh, that's one.
Okay, yeah, yeah, sure.
Lighthouse sounds good.
Now that I talked about vegetables, doesn't lighthouse scores sound a lot more fun?
Well, it's good when they're green.
If you saute a lighthouse score, it's really crispy and nice.
So, what is lighthouse, Dillon?
Well, lighthouse is a tool that is built into Chrome and it gives you some metrics
around your site performance and best practices and accessibility.
If you haven't tried it, then you should open up Chrome, go to the dev tools, click on the
lighthouse tab and generate a report and see how your site's looking.
It gives a lot of interesting information and lots of little low hanging fruit improvements
that you can make to your site.
So, this episode will be about tips around performance, right?
We'll get into performance.
We'll talk about some of the other things for having an Elm application or site that
uses best practices.
There's a lot to dig into.
Some of the things are more Elm specific and some of them are more general web practices.
So, maybe let's go over what kind of metrics a lighthouse gives you.
Well, the thing that people see first and foremost when they open up a lighthouse report
is everybody wants to see the score.
Everybody wants to see a green number, not an orange or a red number.
Ideally, a hundred.
A hundred would be nice.
So, basically the way this works is it gives weight to certain...
So sometimes you can pretty drastically boost that number just by you were missing an alt
tag on an image and you add an alt tag and it dings you quite a bit for that.
There are some little low hanging fruit things that you can do to improve things.
So there's a performance metric and I believe the performance metric gives the most weight
to first contentful paint, cumulative layout shift and time to interactive.
Those are metrics that Google who maintain Lighthouse have been sort of tweaking over
the years to try to get more meaningful heuristics that better reflect a good user experience.
It's worth noting, we're often testing out our sites.
First of all, probably served locally.
Well, that gives me the best experience.
So why should I try it somewhere else?
It's served locally.
It's on a desktop computer.
It's on a multi thousand dollar machine.
Many people are accessing these things on a mobile device, maybe not even a high powered
mobile device depending on your user base.
It's going to be on a small screen.
Yeah, and not necessarily with a high quality, with a fast network.
They might be loading it with 3G.
And that's one of the things that Lighthouse does is it will throttle your network speed
to simulate a slow 3G network, which you can do in Chrome.
You can just go to Chrome or a Chrome based browser and you can go to the network tab
and you can turn on network throttling and see how that feels to use that simulated throttling.
So yeah, I think they've sort of arrived at these key metrics of first contentful paint,
cumulative layout shift and time to interactive as good measures of how users are going to
experience the performance of your site.
So first contentful paint would be if you get a loading screen to the user as fast as
possible or like the skeleton of your app, users perceive that as much faster than, for
example, if you had a blank screen that is clearly loading for a long period of time.
You prefer to see something rather than nothing.
Users are extremely impatient, which is totally understandable if they don't have any indication
that things are happening.
And so first contentful paint is a measure that helps you sort of understand how quickly
do I get something on the screen that indicates that things are happening.
And these things have been studied quite a bit like in the ecommerce space in particular
where you can draw a direct connection between these types of metrics.
You know, your sales numbers and what's the term for people quickly backing out of a site?
I can't remember the bounce rate.
Bounce rate.
So sales are directly connected to these performance indicators.
So that's been well studied that you can have, you know, I don't know, a 10% increase in
sales on an ecommerce site for every however many, you know, 500 milliseconds or less.
I don't remember the exact numbers, but it's significant.
It almost feels absurd.
Like how much difference there is with such a small difference in speed.
Yeah, that just feels unreal to me.
Yeah, it is.
It is pretty amazing.
But also, you know, as a user, you can relate to it that you're waiting for a site to load
and you're just staring at a blank screen and you're just like, you know what?
I don't really need to do this right now.
In those five seconds where you have to wait for the page loading, you can revisit your
life's choices.
Do I really need to buy this?
Yeah, no.
Do I really want to buy this person a gift?
Maybe not.
Do I really like them that much?
Oh, it's loaded.
Okay, I guess I'll do it.
They didn't get me a gift for my birthday this year.
So that's first Contentful Paint.
And you know, you can do certain things like preloading or having a skeleton, you know,
that can help with that.
And you can see in Chrome when you do like performance benchmarks in the performance
tab, you can actually see the snapshots of the loading time.
So you can, which is pretty helpful.
Then we've got Cumulative Layout Shift.
That's like a more recent one that they've started to emphasize in these metrics.
And they used to call it Page Jank.
Oh, yeah.
There's like a classic example.
I actually have a Chase credit card.
So I've seen this many times that you go to like the Chase online like credit card site
to like redeem your rewards points.
And there's, you know, there are like 10 different spinners.
And little by little, each spinner is loading and the page is shifting around, you know?
Yeah, well, at least their first Contentful Paint is probably fast.
They got it fast.
Maybe they were looking at those lighthouse metrics and optimizing for the wrong thing.
And that's probably the kind of thing that was happening that Google's like, okay, people
started doing better on this one score, but how do we capture this thing that feels really
bad now in the user experience?
You know, there are certain things you can do to reduce that, you know, Cumulative Layout
And we'll get into some of those.
But that's one that will make the site feel snappier and just less janky, less glitchy.
I looked up the documentation for Cumulative Layout Shift because I didn't understand the
term at first.
In the docs, they have a GIF, where someone wants to click on, don't buy this item instead
of buying.
So you got two buttons right on the right above each other.
And then right when they're about to click, no, there's a banner at the top popping up
which moves the button.
And so the person clicks on pay.
And then you see the mouse saying, oh no, oh no, it's moving all around and clicking.
No, no, no, no, no, no.
That's amazing.
That made me laugh so much.
It's in the official Google docs.
Sounds like something that Jake Archibald would do.
So that explained it to me very well.
There you go.
That's a perfect, perfect summary.
Love it.
The last big one that's, I think, heavily weighted in the performance metrics is the
time to interactive.
So first Contentful Paint captures how long it takes to initially get something on the
Time to interactive captures, and again, these scores have gotten better and better at reflecting
sort of real things that you feel as a user that make things feel more responsive and
So time to interactive is one of those things that, you know, you go to a site, it initially
loaded something really quickly.
You know, maybe it doesn't have lots of layout jank, so it's got a good cumulative layout
shift score.
And then you go to click on a form field to type something in and nothing happens.
That's time to interactive.
So it's the amount of time until all of the sort of execution for initially setting up
the page have settled.
I have a hard time figuring out when that is a problem.
I mean, in practice, I've not seen pages where the page loads fast, but then it takes five
seconds for it to be interactive.
It actually can be.
So I mean, because, you know, JavaScript is a single threaded environment.
And so you've got all this work competing on the UI thread.
So what will happen quite often is you scroll and it's very shaky and it doesn't feel responsive.
That happens quite a bit.
It's one of those things that when you sort of have the term to describe it, you realize
how ubiquitous it is.
But when you don't have the term, you just feel somewhat frustrated and you don't know
I really wonder how they test that.
I think it's like they wait until the latest large JavaScript execution has settled for
at least 100 milliseconds or something like that.
I was expecting them to find a button or a text field and interacting with it.
And I think your metrics like pretty well capture things that are very much going to
give the user a better experience.
So I like the metrics they've arrived at.
And I think these are good terms to sort of keep in mind when you're trying to make these
So who should be doing these optimizations and be paying attention to these things, Jeroen?
What do you think?
Well, the developers.
If there's only developers in your team, then I would say developers.
Like where is this relevant?
Where is it not relevant?
You know, is it relevant if we have a, you know, back office internal tool?
Is it less relevant there than other places?
Like who should care about this and who should care more, who should care less?
I would say the closer you are to the customer, the more you should care about it.
You probably shouldn't care too much about it for back office or internal tooling unless
it's very slow.
Which can happen.
Because you have not put any effort in the performance of the tool.
So yeah, then if your internal users are complaining, then yeah, do something about it.
Maybe Lighthouse could shed some lights on it.
And I agree that for back office tools, you don't need to get too crazy about optimizing
But also if there's low hanging fruit, why not?
So I think that it's worth running Lighthouse.
I think just being aware of where things stand is a really great idea for any application.
And then I mean, certainly for, you know, as we talked about eCommerce, you can directly
connect that to your bottom line.
And you know, you should really be at that point, if you're an eCommerce company, then
you should really be taking this seriously and tracking it over time.
And you know, maybe keeping a performance budget and tracking big features and how they
affect that.
And aiming for that 100 score.
As far as that's possible, there may be limitations.
But at least being aware, I think everyone in every situation, you may as well be aware,
you may as well run Lighthouse and see what you find and see if there's low hanging fruit.
And you know, Lighthouse, you know, we talked about some sort of some of these metrics that
indicate a good user experience.
And that's one piece of it.
But Lighthouse will also, you know, I mean, if there are, you know, if you're not serving
things over HTTPS, they'll ding you for that.
Incorrectly so.
Yeah, exactly.
Those are the kinds of things that I mean, whether it's back office or not, that's probably
a good thing that you should be aware of if there are issues like that.
Or if you have like SEO, if SEO is important, especially like on a marketing page and things
like that.
Lighthouse is going to tell you some basic SEO things that it's not going to give you
a comprehensive analysis of your SEO, but it'll give you some basic best practices.
All right.
Should we dive into some some specifics here?
Our performance?
Yeah, sure.
So, you know, one one low hanging fruit thing is just using a hosting provider.
Ideally, a CDN.
What is it?
Content Distribution Network?
Content delivery?
Content delivery network.
Yeah, that sounds right.
You know, so something like, you know, I mean, I use Netlify quite a bit, and I've been very
pleased, you know, with their with their free tiers.
People say a lot of good things about Netlify, but there are there are other options as well.
But that's something that I think is a low hanging fruit performance improvement for
a lot of people.
Like one of the reasons that a CDN helps is that it it serves up your, you know, static
assets, your, you know, compiled Elm code and, you know, if you have your entry point
HTML, and it serves those assets at the edge.
So at the at the nearest location, rather than having to request something to a server
and send it back from AWS East or something like that, it's going to serve it at the nearest
servers, because it's just a static file.
So it doesn't need to hit a specific server in a specific location.
Yeah, it acts as a cache proxy, right?
Mm hmm.
Mm hmm.
Yeah, exactly.
CDN is effectively your everything is just cached because they're static files.
So there's no sort of intelligent caching to do for serving static files.
I mean, I'm sure there is plenty of optimizing they do around that.
But it's pretty simple, just put the files a bunch of places and serve them as fast as
you can.
And that'll take care of HTTPS and give you certificates.
And it's quite nice.
So I recommend taking a look at Netlify or similar CDN services.
Yeah, I think Netlify serves your your website.
But if you if you if you don't need it to serve your your server, you can use other
CDNs, which just acts as a proxy between your server and the user's computer, which Netlify
probably also does.
But I'm not aware of that.
Are you thinking of like, what is it cloud flare?
Or I haven't used those myself.
But that's the kind of thing we did at some of my previous workplaces.
Mm hmm.
Yeah, yeah, nice.
So those are some, you know, I mean, those are some things that don't require a ton of
engineering effort, but they'll give give you some performance gains that'll make Lighthouse
a little happier and make your users happier.
How do you make that work?
Because as you said, like, you just put a static file on a CDN, or you have it serve
your file.
But what if your file changes?
Like what if my index.html has changed since I since it was last served on a CDN?
Well, for like an index.html, it's, it's not going to do file based hashing, because that's
the entry point.
That might be a bad example.
But for something like an image, you can certainly, you know, use tools, you know, have a webpack
config that uses file based hashing and sets like a long cache period and uses the file
name for cache busting.
Yeah, there's a whole set of practices around that.
Yeah, so adding the hash to the file name, and replacing every occurrence of that in
your source files, CSS, HTML, JavaScript files, right?
So that whenever your file changes, you get a new hash or version number for that file.
So you don't request the old file anymore.
For images.
So one of the, you know, one of the biggest areas of low hanging fruit for these performance
improvements on a lot of on a lot of websites is images because yeah, you know, if you're
serving like a big one megabyte image, which is not uncommon that you know, some somebody
doesn't really think about that, and they just put the image there.
Okay, it is really important that our JavaScript files are less than 100 kilobytes, right?
Big, right, right, and then you do a lot of work to make that work.
And then someone puts very big images on your website.
Now actually, that said, there is a much greater cost to, you know, per kilobyte of JavaScript
versus images because images, yeah, they're just rendering them.
Whereas JavaScript, you know, when when the JavaScript comes down the wire, you decompress
the asset that just loaded.
So even if it's, you know, whatever, it's like 100 kilobytes, compressed and 200 kilobytes
Well, now that that's computation that needs to be done to decompress it.
So sure, you saved some, you know, bandwidth over the wire, which is great, but there's
computation to be done.
Now once it, you know, decompresses that it needs to, it needs to exactly it needs to
parse it and then execute it.
So it's extremely expensive per kilobyte of JavaScript.
And until it has all been decompressed, read, parsed, executed, you don't have anything
to show.
Yeah, well, that's yes.
And at least in Elmland.
So that impacts the first contentful paint, right?
Unless you're doing some sort of pre rendering.
And that's that's another that's another topic.
But and we'll get into some of those things a bit.
Yeah, you can have a big size gains for images at least.
So for images, what what I've started doing that I've been really happy with is using
Cloudinary and there are other similar services.
I haven't used other ones, but I've been very happy with Cloudinary.
You just, you know, upload your image assets there and it takes care of serving up a performant
optimized image.
And so like the way that it works with Cloudinary, you upload the image and then they have like
a URL based API for saying I want it at this width.
I wanted it this height.
I want it at this quality, this format.
And on their servers, they'll take care of doing it.
And it's I mean, that's what they do.
So they're able to optimize these images extremely quickly.
Do they also cache it through a CDN for you?
Yeah, I mean, I think the the serving is all they they take care of all of that for you.
So it's served up as efficiently as possible.
And not only that, but like you can set automatic quality, which is quite handy.
So you can say, I'm going to serve it at these dimensions, this width and this height.
But you pick the best quality that basically, you know, if you can compress it to 20% quality
and it's going to not deteriorate the quality noticeably, then fine, like I'll leave that
to you instead of just picking a quality number and going for that.
It will it also gives you the ability to do auto format.
So to automatically pick an image format.
And so what that will do is based on the incoming request, it can tell the agent, the user agent.
So it can tell if it's loading from Chrome or Safari.
And then it's going to, you know, if it's on a browser that doesn't support WebP, then
it's going to serve a JPEG.
If it's coming from Chrome, which supports WebP, then it'll use WebP, which, you know,
compresses down a lot smaller.
I think we should say that this was not paid advertiser.
Unless you want to Cloudinary.
Unless they want to pay us.
Yeah, feel free.
And until they do, there are probably alternatives to this.
Yeah, I haven't played around with alternative solutions, but I've been very happy with Cloudinary
and just in general, this approach of offloading that work to, you know, some service that
just does that very well.
I think it makes a lot of sense.
I recently, you know, with Elm pages, I was doing a lot of like sketching for an API to
allow you to sort of specify image optimizations to perform a lot like Gatsby's image optimization
I had this realization, you know, some like Chris Biscardi, who's worked on some Gatsby
features and has his own static site generator tool now influenced my thinking on this a
lot with talking about like this bloat that comes from doing image optimization during
your build step.
It adds a lot of time to your build step.
So I mean, there are other ways to do this.
There are like you can wire up a GitHub action to go into your GitHub repository and optimize
But in general, like just optimizing some an image during your build step is going to
bloat your build quite a bit.
And it's probably not going to do as good a job as something like Cloudinary or a similar
service, especially if you're trying to load it at, you know, 10 different responsive breakpoints.
And that's like sort of another area that can really give you some like serious wins
is like if you're on I mean, let's say you have like a I don't know, a photography portfolio
site, right?
And you want like really crisp, clean photos, but somebody's viewing it on a tiny phone.
You don't want to serve the, you know, 4000 pixel wide, ultra HD, high res version, right?
Maybe they're missing out if you don't do that.
In many cases, they're going to have a worse experience, you know, waiting for it.
And you know, the size may not even be perfectly suited to display properly because there aren't
enough pixels to display.
So it's better to have the correct number of, you know, correct width.
So just, I mean, I just felt a big relief giving up on the idea of doing that in my
build process and just making that someone else's problem.
And like for the website, I actually made a change recently where I moved the assets
over to Cloudinary and I made like a little responsive image helper.
So it sets the source set, SRC, SET to give you all these different breakpoints for the
So it's going to, and then it just tells Cloudinary like, all right, like if it's a device with
at least this width, then serve it at this Cloudinary URL, which specifies the width.
And it says automatically pick a quality for me, automatically pick an image format for
It just says, this is the width.
It's super easy to write a little elm function that does that for you.
And you're just like, you're going to end up with way better performance and it's going
to be way easier than trying to like set up all these scripts to optimize images for you
and stuff.
So I was very happy to like just give up on the idea of having my own build tasks to do
that work.
And now you deploy much faster too.
Well that's, yes.
Oh man, that was an interesting, I still have not solved the mystery of this one line change
I made in the Elm pages source code that took our builds from like 15 minutes
to under two minutes.
Still have not solved that mystery, but it's faster.
So I'm happy.
And then on the topic of images.
So another sort of low hanging fruit thing you can do is this lazy image loading.
So I think you just say like lazy equals true or something, right?
On the image attribute.
I actually don't know what that does.
Oh, you're not familiar with it.
And I looked up the syntax to refresh my memory and it's, so in your IMG tag, you say loading
equals lazy.
And that's supported in Chrome, Edge, Opera, Firefox, and the Safari implementation is
in progress.
It's going to degrade gracefully and just not do anything on browsers that don't support
So what it does is if an image is scrolled into the viewport that you're currently viewing
on the page, then it will make sure to load it.
If it's not, then you scroll down and it starts to load it.
So it doesn't, so if you know.
That's how it's done.
Oh, that's much simpler than I thought.
It's extremely simple.
I mean, for the most part, there's not really a reason to not do that.
There may be some cases where you, you know, maybe you don't have a ton of image assets.
There's just like one extra image and it's not worth that small savings to, you know,
scroll and then see it pop into appearance.
But you may as well play around with it and see how it feels.
And on the topic of image optimization, a really big win is if you can use an SVG instead
of a JPEG or PNG.
It's just going to give you, it's purely a win.
It gives you the best quality and performance.
Is it smaller in size always?
Generally it's going to be smaller in size.
I mean, perhaps if you have like an extremely complex shape, there could be certain instances
where it's not going to be as optimal.
But for the most part, and especially with like more simple shapes and logos, it's overall
going to be a big win in most cases.
Especially if you try to make the image very big.
Then you don't have to download the big image.
You just have to download, well, the same thing as for a small icon or the small image.
Sometimes I look at the HTML files of websites and I see some icons for Mac, I think, with
a lot of...
Like 40 of them?
Yeah, 40 of them with different sizes and all.
Do you know what that is all about?
I do.
I know it all too well.
You say with such enthusiasm.
Good times.
Andrew, I know about these icons just as well as I know ISO 8601.
I love when you say that.
These icons, it's one of these things that's gotten a little bit unwieldy where you have
an Apple touch icon and you have an icon for a Microsoft phone and for whatever device.
It's a lot like these vendor prefixes in browsers where you start having your CSS be like, oh,
Firefox has this one CSS feature and Chrome implemented it differently so you can fine
tune it based on these slightly different implementations and things like that.
It's very similar to that.
It's the kind of thing where a lot of the tags that are put on there are for iOS 5 and
iOS 5 has certain requirements that the icon that it would use if you create a bookmark.
You create a bookmark and now it's on your home screen and that's the icon it's going
to use for that.
Then if you create a bookmark on a Microsoft computer, then it's going to use a different
There are these services that will just generate those for you.
That's for an older version of iOS?
There are ones for older versions and then there are ones for newer versions.
It is still recommended and Lighthouse will ding you if you don't include certain ones.
You may be shocked, Jeroen, but I used Cloudinary to generate those for the site.
I'm so shocked.
It's just one of those things that you just get the right ones and get them on there and
it makes Lighthouse happy.
Who knows, maybe nobody will add your site as a bookmark and it will never make a difference,
but at least Lighthouse will be happy about it.
I imagine that I would add them until Lighthouse stops letting me know about problems.
That's a reasonable way to go.
I've been trying to encapsulate that in a little helper function and as something that
can be shared for Elm pages sites.
There's another set of icons that Lighthouse will tell you about.
You've got in the manifest.json.
The manifest.json is just a JSON file with a specific format of data that it expects.
That data is to tell it about a so called progressive web app.
What that means is if your website meets certain criteria, served over HTTPS, has a service
worker, I think it may even need to meet certain performance attributes, but it certainly needs
to be secure.
You can't run a service worker on a page if it's not served over HTTPS because it's a
man in the middle.
It can intercept HTTP requests and change them.
It acts as a proxy, the service worker.
It can intercept those and tweak them and give its own responses.
It needs to be served over HTTPS.
If you have a website that meets those criteria enough to be deemed a progressive web app
by the browser that your user is loading your site in, then they will be presented with
an option to install your site as an app.
Or they can just go in and manually save it on an iPhone.
In Safari you say save to home screen.
I think the same thing on Android.
If you do that, then there are a few things that are going to feel more like a native
It's going to have a splash screen when you load the app, just like a native app would.
It's going to have an icon that's supposed to look like a regular app icon.
So you need that set of icons that you specify.
The manifest.json has a set of icons.
You can set certain things like does it have a URL bar or not.
If you want it to feel more like a native app, you can opt out of the URL bar so you
can configure certain things like that.
You can set categories for listing it in certain app stores.
Microsoft has, I think, gone all in on making progressive web apps installable.
So I think the official Windows Twitter app is just a progressive web app.
It's just their
It's pretty cool.
There's varying support for progressive web apps, but it's quite a neat approach.
The Twitter web app is the only one that I've used until now.
I find it much better than the native application.
So that's a good example.
Yeah, I mean it makes sense.
Just this concept of a progressive web app makes sense because you go to a site, maybe
you're not going to use it forever.
Maybe it's like a conference page or some event.
You don't want to install a whole app or create a whole app for that, but you can have a service
worker and set it to make certain assets available offline.
So that's a whole other can of worms of how you approach caching those assets for offline.
I'm working on an API for Elm pages where you can sort of specify which pages should
be available with which cache policies.
Available upon install, cached as soon as they're loaded, and then available offline
after that.
You can do stale while revalidate, which means every time you request the asset, you immediately
request the fresh copy of that, but then you serve up the old copy that you have cached
if you have one.
Yeah, in the meantime.
So there are all these different cache strategies.
There are tools like Workbox is this Google tool that gives you a more high level way
of working with the service worker API and specifying specific assets to be cached and
generating a sort of manifest that tells you which files need to be cache busted in the
latest service worker and maintaining things like that.
It's complex and it's very difficult to get a service worker right to get that caching
done right for an offline experience.
I mean, I think it's a really exciting space, this area of progressive web apps.
Yeah, definitely.
So Lighthouse actually tries to run your website as a progressive web app.
It will tell you when it does and when it doesn't.
So I tried running it on Elm Radio and it is not a progressive web app and tells you
it is not because it does not do this, it does not do this.
So essentially, yeah, it doesn't give you a 200 response when it loads the main landing
page, if it's offline.
And yeah, on Elm pages, so is built with Elm pages and I don't have any
service worker stuff right now because I want to sort of create a really good service worker
It's an inherently complex problem to figure out the cache policies for things.
It's not getting an offline ready web application is not like a drop in thing.
What if you're making dynamic HTTP requests to some real time data?
What you do not be cached to.
Yeah, exactly.
You can't cache that.
So you can go as far as having a local database and sending and syncing data.
There's like a service worker API for syncing data.
So the service worker will sort of store that data.
If you add something to your shopping cart and then you're offline and then you get online
again and it notices that there's something that's not been synced and it makes that request
to get it in sync.
That's not a drop in feature that you just say, please make this a service, please make
this an offline ready progressive web app.
That's something that requires a thoughtful design to make these sort of user experience
and technical decisions.
So I'd like to give a good API for doing that sort of thing with Elm pages, but I want to
do it right and I want to give that the attention it deserves.
So once that's done, I think it would be super cool to have the ability to make a little
offline ready page that you can install as an app.
Yeah, definitely.
What I really like with Lighthouse is that it tells you about all those things that are
missing or that are not great.
Now I know just by reading that what I need to do to make it a progressive web app and
there are links to documentation and all that.
I found that really helpful.
It's almost like static analysis tool.
You like static analysis tools?
I think they can be useful, but you shouldn't overdo them.
You shouldn't spend too much time working on those, I think.
So on this topic of progressive web apps and offline ready, Luca Mugg has this Elm starter
project that he's built and it takes care of that.
The idea is to make it a lightweight wrapper around a plain Elmap that you don't build
it to this frameworks API, but you just drop in a few things and connect it to an Elmap.
So that's something to look into if you want to just take a landing page that's an Elmap
and it's not going to help you sort of set up syncing your offline transactions and stuff
in the background and things like that.
That's not the intention, but it's more like here's an Elmap and I want you to be able
to install this and load it offline.
It's a great tool for helping you do that.
Or a good resource if you need to go further.
Do you want to go over what else Linus gives us?
So what I see is that it gives information about multiple topics.
So one of them is performance, which we've covered already.
Maybe not in full, but we've covered it.
There's a lot.
You can go down a lot of rabbit holes with performance.
Yeah, I think so.
Three others are accessibility, SEO and best practices.
I have no clue, but best practices actually.
Maybe before we move on from performance, it's worth just noting a couple of last things.
One is make sure that you're using dash dash optimize when you build your Elm bundle.
And also make sure that you're using Terser to do the minification and dead code removal.
Is there any difference between Terser and Uglify or Uglify JS?
Terser is like the new way of doing it.
Uglify has since been deprecated, but it's effectively the same.
And I think Terser worked with ES6 or ES2015, which we don't care about for Elm, but yeah.
So that's like a low hanging fruit.
If you're not doing that, you really should.
If you try to use the dash dash optimize flag in your Elm app and it's complaining, then
remove those debug.logs and those debug.todos from your production app.
It's worth taking the time to do that.
Help your Elm code not crash.
Also Matt Griffith and Simon Twop have done this really cool project, Elm Optimize Level
And that's worth checking out.
You could try it out, see how it affects your performance score.
It's just something that you use to compile your Elm app and it runs some sort of static
optimizations on the JavaScript output that make it run better in the JavaScript runtime.
Pretty cool project.
I think it tries to optimize for speed, but not necessarily size.
Am I correct?
That might be correct.
It's definitely worth looking at what numbers it gives you.
Like most things when you do work with performance, run benchmarks.
That's right.
And a really good tool too for performance benchmarking is if you go to the performance
tab in your dev tools, you can...
In your browser?
Then you can go to hit this little record button and it will capture the JavaScript
execution and which functions are taking the longest.
We can link...Julu has a really great blog post that talks about how to analyze performance
bottlenecks in Elm.
I've used that technique many times and if you're finding that you have some performance
bottleneck somewhere, that's quite a useful technique.
And then one last point about performance.
If you have...HTTP2 kind of had this HTTP push concept of you request a certain page
and your server is able to say, oh, you requested this page, but since it's that page you requested,
I know some other assets you're going to need, so let me send those over to you.
Now that has sort of failed.
That spec has had some failures and it's turned out, I think essentially the bottom line is
technically it was extremely difficult on the server side.
It was difficult to implement that consistently serving up the correct assets.
And now the recommended practice Netlify, for example, used to have support
for HTTP to push and they dropped that some time ago.
The recommended practice these days is to use preload tags.
And so preload tag is just a link tag that you put in your head of your HTML.
It's link rel="preload", href="something.js", as script.
We'll put a link to something with more information about that.
But that's another thing that can sort of help.
So what that does is you don't need to execute all this code to know what assets are going
to need to be fetched because what the browser is doing is it's parsing everything in order
to figure out what it needs to fetch.
But if it sees a preload tag before it parses it and figures out the dependency tree, you're
giving it a hint that says, hey, by the way, as soon as you see this in the head tag, go
and fetch this asset, you're going to need it.
So that's a helpful thing.
So does it fetch it before other things that are more urgent or does it wait until everything
else has been downloaded?
There are different priorities for the fetches and I think it'll give it some sort of medium
priority, not necessarily the highest priority, but it will do its best to squeeze that in
there so it's ready when it needs it.
But the way that rendering an HTML page works is there are certain things that need to be
done before it can continue with execution.
So if you put a script tag in your head tag, then what it's going to do, so you say script
and then you link to some source for the script.
So you fetch the HTML, it has that script tag, so now it's parsing the HTML because
it doesn't understand it yet, it needs to parse it.
And it gets to that script and then it says, uh oh, I can't do anything else until I've
fetched, decompressed and evaluated this JavaScript code because the JavaScript code could modify
the HTML page that it's going to render.
And that JavaScript code also, the next script that's in there could also be dependent on
the previous one.
You have to load jQuery before you load the main script.
So in order to prevent that, you can use the defer tag on scripts and we'll link to a resource
about the Google web performance team's recommendations on that.
There are a lot of different resources that talk about how to do this, but in a nutshell,
it tends to work pretty well if you added a defer tag to the script, because what that's
going to do is it's just going to say, you know what, you don't need to block rendering
the rest of the HTML and continuing to fetch all of the images and scripts and assets that
you determine need to be fetched.
You can just come back to this JavaScript when you get there and load it when you're
done showing the page initially.
Please do my first contentful paint first.
Now if that's just like an empty HTML page, then you might want to prioritize that differently.
So I mean, pre rendering Elm starter, it does some pre rendering and Elm pages does pre
So if you are doing some sort of pre rendering Elm pages just does this script defer for
So it will give you a faster first contentful paint.
Okay, so that's good for performance.
So maybe let's talk about SEO then.
From what I can tell from the latter's report, SEO tells you more about things like user
experience, especially with regards to mobile, for instance, like making sure that your page
shows up correctly on a smaller device than if it was on a desktop device.
I think that would be under best practices.
I see it under SEO like the meta name viewport.
I don't know.
Oh, you're right.
It is under SEO.
I guess I did know then.
I do see that one under there.
That's interesting.
I'm not sure why.
But yeah, so I guess yeah, it's saying to do to make it mobile friendly under SEO.
Oh, you know what?
You know why it's under there?
Because otherwise Google will declassify you in search results, I'm guessing.
Yeah, exactly.
Yep, that's right.
It will ding you in your page ranking if you violate these certain basic mobile friendly
So if you care about SEO, you really want a good score on this.
And is it possible to get 100?
I don't know if it's easy.
I'm guessing you just mostly...
It's fairly easy.
Yeah, it's fairly easy.
And one thing like with, you know, responsive pages.
So yeah, there's that little magic incantation, that tag that you put in there that just makes
Google happy.
The metaname viewport and the, you know, initial scale and all that.
Which I know nothing about, but there is a link.
So I'm guessing that I could learn more under the learn more link.
We'll include a link to that.
It's just one of those things you do that...
So sometimes what will happen, people used to do things like disabling zooming in on
a page.
Have you ever gotten to pinch to zoom on a web page on your mobile browser and it won't
let you zoom?
That's a good point.
It's really, it's bad.
It's also bad for accessibility.
So if somebody, you know, doesn't have perfect vision, you know, if they're visually impaired,
then they may need to zoom.
Also if you're not visually impaired, you may need to zoom.
It's just like, you know, accessibility is something that's good for everybody.
And some of these basic things that Lighthouse tells you about are good ideas in general.
So that's, yeah, you just put that magic incantation and it's going to set aside that full width
on mobile and look good there.
And for making responsive web apps.
So like if you're using Elm UI, you want to be careful about making sure you're wrapping
things in paragraphs as needed because a paragraph is going to not overflow, but it's going to
So basically anytime you load your mobile app and there's an overflow where you like
have to scroll to the side and like part of the text hangs off of the page, that's a bug,
So Lighthouse will tell you about that.
Under SEO or under accessibility?
Maybe under SEO.
Those are important ones to get right.
And then some of the more, you know, what we think of as more typical SEO things like
getting the right metadata on your page.
You know, there are some basic ones like, you know, you're supposed to put a language
on your document.
So put that in your HTML.
You're supposed to put a canonical URL.
So what a canonical URL is, this is actually important to get right.
You can be penalized quite severely if you get this wrong.
If you have your site hosted in multiple pages or if you have like any duplicate, you know,
pages or places where you serve up a site, Google will flag that as potentially being
spam and it can be really bad for your search rankings.
Like they can put you, they can punish you for that.
And so you need to, if you have duplicate content and duplicate places where you host
the same site, you need to have a canonical URL.
And what that's saying is, yes, this page is in two different places, but this is the
main one.
Like if somebody searches on Google, show them this one because this is like the proper
URL for this.
So that makes me think about, that makes me wonder, should I run Lighthouse on a single
page of the website or should I run it on several pages?
Because it can, like my homepage could be great, but when I go to the about page or
contact page, whatever, it might tell me there are plenty of problems.
That's a good question.
Does Lighthouse even try to crawl your website or?
I don't believe it does.
I don't think so either, but.
I'm not sure if does either.
[00:52:49] like runs these Lighthouse metrics, but it actually will perform them
on like mobile devices.
And there are some different tools like this that I don't think they do that, but it's
not a bad idea.
I think of this as like an art more than a science that, you know, it's just like the
more information, the better.
And you know, yeah, you may as well run it, run it on multiple pages.
So I've thought a lot about like these sort of open graph SEO things and that sort of
So we can talk a little bit about that.
In a nutshell, I think that if you have a marketing page, a conference website, a portfolio
page, a blog, you know, if I send you a link to a blog post that I wrote, you know, or
I send you a link to my resume site or something like that, I don't want to send you the link
and then in Slack it like doesn't unfold properly or on Twitter it like gives you an anti climactic
That it just, it feels unprofessional to me.
And if I put in time and effort to make a polished site or blog post or whatever, I
want a nice preview because previews like previews just make things look more official
and authoritative.
To me, I don't trust links if they don't have a good preview.
So you don't trust any links to my blog site?
Do they not have?
I did not put any effort into that.
It may have it.
It may have it.
I think it does, but the logo.
It might have the Gatsby logo on it.
It has the Gatsby logo.
So I think it's because it's not an Elm pages website yet.
So I think it's worth putting a little bit of love into those things.
And I mean that, you know, as we've talked about, that was one thing I felt was really
important in Elm pages was to make that a good experience and to use type safe API to
guide you towards doing that with confidence rather than like reading, having a hundred
tabs open and finding blog posts that tell you what, you know, head tags you should put
in your page or whatever, you know?
So I think it's worth getting the Open Graph tags right, putting a little effort into that
or using Elm pages, another option.
And yeah, and you can, I mean, that's the basics.
Just getting the Open Graph tags, which are going to give you the previews in Slack, Twitter,
various social networks, which I shall not name.
You already mentioned a few.
And like if you send a text message, it's going to unfold properly and things like that.
So I think it's really nice to have, if you preload your pages, it's going to tend to
do that, you know, more reliably because not all services will execute JavaScript in order
to get a preview.
Scan for those meta tags to give you a preview.
So that's definitely worth doing.
And I don't know that Lighthouse will tell you about Open Graph tags actually.
I think it will just tell you, you know, your page should have a description and a title
to make search engines happy and some basic things like that.
So I mean, and just in general, like having a good Lighthouse score, perhaps it's necessary,
but not sufficient.
I was wondering, like, when you get to a very good score, like 96 to 100 on every metric,
do you stop or do you continue somehow?
Oh, definitely.
You definitely continue.
It's just the starting point.
And in fact, there are several places where Lighthouse will give you a manual set of audits
to perform.
And it says like, these aren't automated, but you should run through this checklist.
Oh, cool.
We'll link to that.
I don't think we'll be able to go through best practices and accessibility at this point.
There's so much.
We actually talked about several best practices already.
We talked about serving things up with HTTP2.
And if you use a CDN, it's going to give you the proper compression and things like that.
I mean, a lot of these things are really just run Lighthouse, see what it tells you.
If you can just do it, do it.
If you need to research it a little bit, spend a little time, see if you can do it and make
Lighthouse happy.
It's a useful tool.
I think you will find quite a lot of low hanging fruit.
To get you started.
For accessibility.
So I'm certainly not an expert in accessibility.
Lighthouse is also not an expert in accessibility.
It's only going to tell you about some basic violations.
I mean, there are some useful things.
It's going to tell you if your contrast ratio isn't high enough.
If you have, you know, if you have a yellow font over an orange background, then it's
going to tell you.
People might have a hard time reading that.
If you don't have an alt tag on images, it's going to be unhappy about that.
And as it should be, you know, there's some basic things like that that are just really,
it's not rocket science.
You should definitely do it.
But it's definitely not like, oh, I get a perfect accessibility score on Lighthouse.
Therefore, somebody can, you know, use a, you know, a voice, a text reader to navigate
my site.
No, not at all.
There are more robust tools for analyzing that.
Like Axe is a popular accessibility tool.
It's worth looking at.
So essentially, but some of the wisdom that I've heard about accessibility is that people
talk a lot about ARIA tags and there's a lot in Lighthouse about ARIA tags.
And one of the things I've heard is that, so Lighthouse is going to complain if you
improperly use certain ARIA tags, but in general, ARIA tags should be your last resort.
If you can make something accessible without using ARIA tags, then it's better to do that.
Using proper HTML tags, for instance.
Right, exactly.
Because it's not, you know, ARIA tags are really designed if you're doing like very
nuanced things with JavaScript and, you know, JavaScript carousels and things like that.
And you need to announce changes and things like that, then ARIA can help you there.
But for basic things on just a static website, usually you won't need ARIA to specify those
things and make them accessible.
So you want to reach first for, you know, semantic HTML, you know, having real buttons,
headers, footers.
And then there at the bottom of the accessibility, we'll link to this.
There's additional items to manually check.
So again, you know, it's the starting point for accessibility, not the be all end all.
But if you don't have perfect score, then start with that.
All right.
Well, I think we've given people a lot to chew on.
Any last things we want to hit on?
I was wondering how to run Lighthouse to start with.
So what I did was search for Lighthouse on Google and then gave me a website to run it.
So that's what I tried.
And then at the beginning of this episode, you reminded me that it was inside the browser
to start with.
I knew that, but I totally forgot about it.
Oh, okay.
Then we should definitely repeat that here.
If you want to get started, I actually use Brave as my browser, which is based on Chromium.
Now Lighthouse seems to have trouble running in Brave.
So what I do, maybe that's different in the latest version.
I just open Chrome.
I just go to Chrome and I...
You don't have all your extensions that impact performance, for instance.
I'm not sure if it takes that into account or not.
But yeah, it's not a bad thing to have like a sort of vanilla plain browser and have it
use that for that benchmarking and stuff.
Just open up the Chrome DevTools, click the Lighthouse tab and say, generate report.
So while researching that, I am someone who really likes to work in things and then making
sure that they do not regress.
So I looked at whether you could run Lighthouse in your CI and there is a Lighthouse NPM package.
So you can just run Lighthouse in your CI or in a custom application that you make,
if you want to.
And you can create a history if you want to get clever with it.
You can set a threshold.
And then you can configure your CI with a custom script that checks whether things have
gotten worse or compared to a history or, I don't know, compared to a budget.
So I'm not trying that out, obviously, but I thought that was interesting.
So you can use it to get analytics and find out where you can improve, but you can also
use it as a regression tool.
Probably not the best one.
I'm guessing they're most specialized tools, but if you have CI workers to spare, then
maybe it's useful.
Yeah, yeah, definitely.
Yeah, it's not a bad idea to run a tool like Axe as well for checking accessibility in
a more robust way.
Netlify has a plugin for Lighthouse as well.
I haven't used it yet.
It was created pretty recently, I think.
That's something I want to check out.
It seems like a good way to do it.
All right.
Yeah, I think there are plenty of things to talk about about Lighthouse performance, accessibility,
and maybe we'll talk about that in other episodes, but I think we covered quite a lot already.
I think that should give people a good deal to think about.
And also, if you want to get started with this stuff, again, just run Lighthouse, see
what happens.
There's also, which is this website that the Google dev rel team maintains.
They do a really good job giving you these resources on these best practices and modern
web practices.
There's a whole section that talks about Lighthouse audits.
When you run Lighthouse and it flags an issue, it does a really good job linking you to a
thoughtful article that gives you resources and reasoning behind these things.
Lots of good resources to help with these basic practices.
It's just a basic, you know, basic hygiene, you know, web app hygiene sort of thing that
I think any Elm app should be looking at these basics and at least aware of issues.
Yeah, definitely.
All right.
Well, thanks for listening and give us a rating on Apple podcasts.
Check us out on Twitter and ask us a question.
Elm dash radio dot com slash question.
Let us know what you'd like to hear about next.
All right.
See you next time.
See you next time.
Happy performance tuning.