Journey to a
performant website

Prashant Palikhe
Nepal 🛫 🛬 Netherlands
@prashantpalikhe
What is fast enough?
90+ on Google PSI
< 1000ms SpeedIndex on WebPagetest
90+ on PWA Lighthouse
Profiling & analysing

Content efficiency
whatdoesmysitecost.com
Compress and cache
Easily achievable by configuring web server
h5bp/server-configs
Gzip text-based assets
Brotli for higher compression





Include image optimisation in build process
Use progressive jpegs
WebP for ~30% savings


<picture>
<source srcset="2x.webp 2x, 1x.webp 1x" type="image/webp">
<source srcset="2x.jpg 2x, 1x.jpg 1x" type="image/jpeg">
<img src="fallback.jpg" alt="">
</picture>
Lazy load images
Intersection observer to detect elements in viewport




// create observer
const observer = new IntersectionObserver(onChange);
function onChange(changes) {
changes.forEach(change => {
// take image url from `data-src` attribute
change.target.src = change.target.dataset.src;
// stop observing the current target
observer.unobserve(change.target);
});
}
// convert node list to array
const imgs = [ ...document.querySelectorAll('.lazy') ];
// observe each image
imgs.forEach(img => observer.observe(img));
requestIdleCallback() to prevent scroll jank



Optimize web fonts
Use lightweight woff2



Font-loader to get around lazy font-loading

Render text asap with system font
Render actual font when available
<style>
body {
font-family: Arial, sans-serif;
}
body.has-fonts-loaded {
font-family: "My fancy font";
}
</style>
<script>
someFontLoader
.load('My fancy font')
.then(() => {
document.body.classList.add('has-fonts-loaded');
});
</script>
Using system UI fonts
body {
font-family:
/* 1 */ -apple-system, BlinkMacSystemFont,
/* 2 */ "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans",
/* 3 */ "Helvetica Neue", sans-serif;
}
<link rel="preload" href="font.woff2" as="font" type="font/woff2" crossorigin=""> />
Cache your static content
cache-control:immutable
to prevent revalidations



Trash junk CSS/JS
DevTools coverage
Inline critical CSS & load the rest async
Critical CSS within
first 14kb
TCP starts slow
addyosmani/critical
github.com/
Eliminate network
Service Worker
// index.html
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js');
}
[1/4] Download
// sw.js
self.addEventListener('install', (event) => {
// Prime your cache
});
[2/4] Install
// sw.js
self.addEventListener('activate', (event) => {
// This SW is taking control, clean up old caches and do migration work if needed
});
[3/4] Activate
// sw.js
self.addEventListener('fetch', (event) => {
// Intercept network requests, resolve from cache if hit.
});
[4/4] Intercept
🏅100 on Google PSI
🏅~1000ms SpeedIndex
🏆 100 on Lighthouse
Thanks!
Journey to a performant website
By Prashant Palikhe
Journey to a performant website
- 798