Building a Fast Website for every single visitor
What makes the web user so special?
2G
3G
4G
5G
@med7atdawoud
Developers are privileged
Building a Fast Website for every single visitor
More Accessible
Medhat Dawoud
Senior Software Engineer at Miro
Google Developer Expert in #WebPerf
๐ @med7atdawoud
medhat.dev
Performance depends on the user perception
๐๏ธ
๐
๐ดโโ๏ธ
๐น
Wow, this is so fast ๐คฉ
Oh no, this is so slow ๐
Would a motorcycle be considered fast or slow?!
๐๏ธ
๐
๐ดโโ๏ธ
๐น
๐๏ธ
It is slow
It is fast
#2 Field Testing
#1 Lab Testing
How to measure performance?
Core Web Vitals
Device Distribution
Connection Distribution
No one-size fits all
Pick a Target
๐ More A11y but poor UX
๐ poor A11y but great UX
@med7atdawoud
To build a web app for the user with guaranteed conditions
To build a web app with cutting edge tech for best user conditions
๐ข
๐
low-end
high-end
๐
๐ข
low-end
high-end
Or, build for everyone
๐ Best A11y and best UX for everyone
@med7atdawoud
a web application that can adapt to user conditions
๐ฅณ
๐ฅณ
low-end
high-end
๐ฅณ
๐ฅณ
low-end
high-end
๐ฅณ
๐ฅณ
low-end
high-end
Core features
Glory UX ๐
And Best DX
Graceful Degradation
Progressive Enhancement
What user-related factors are beyond our control?
@med7atdawoud
Screen Sizes
Browsers
Device (CPU + RAM)
Internet connection
What user-related factors are beyond our control?
@med7atdawoud
Seating position
โ
โ
Seating position
Screen Sizes
@med7atdawoud
Components should be responsive like water
Components should be responsive like water
Cats
Images are 60-70% of a webpageโs total size
<img
src="spaceX-mechazilla.jpg"
alt="SpaceX Mechazilla" />
Regular HTML image tag
@med7atdawoud
~500KB
~500KB
~500KB
> 1024px
< 800px
< 480px
<img
srcset="spaceX-mechazilla-480w.jpg 480w, spaceX-mechazilla-800w.jpg 800w"
sizes="(max-width: 600px) 480px, 800px"
src="spaceX-mechazilla-800w.jpg"
alt="SpaceX Mechazilla" />
Responsive Images
@med7atdawoud
~500KB
~100KB
~36KB
> 1024px
< 800px
< 480px
Responsive Images (OOTB)
@med7atdawoud
https://developer.chrome.com/docs/aurora
<Image src="/me.jpg" />
๐ค
<img
srcset="
/_next/image?url=%2Fme.jpg&w=640&q=75 1x,
/_next/image?url=%2Fme.jpg&w=828&q=75 2x
"
src="/_next/image?url=%2Fme.jpg&w=828&q=75"
/>
Input:
Output:
pixel density descriptor
const sharp = require('sharp');
const fs = require('fs');
const directory = './images';
fs.readdirSync(directory).forEach(file => {
sharp(`${directory}/${file}`)
.resize(200, 100) // width, height
.toFile(`${directory}/${file}-small.jpg`);
});
Server Different Images with different sizes using Sharp or ImageMagick
Or use an image service like Cloudinary or Vercel
@med7atdawoud
Browsers Support
@med7atdawoud
What causes a feature to be unsupported by a specific browser?
Gecko
Blink
Webkit
Blink
Rendering Engines
Blink
SpiderMonkey
V8
Nitro
V8
JavaScript Engines
V8
How can we determine if a feature is now supported?
Use Web APIs from the future
if("share" in window.navigator) {
} else {
// use regular 3rd party lib
}
await window.navigator.share(info);
Images (Again?)
<picture>
<source srcset="photo.jxl" type="image/jxl" />
<source srcset="photo.avif" type="image/avif" />
<source srcset="photo.webp" type="image/webp" />
<img src="photo.jpg" alt="photo" />
</picture>
@med7atdawoud
<img src="photo.jpg" alt="photo" />
โ
โ
Lossless 50:1 compression
Browserlist
@med7atdawoud
{
"browserslist": [
"> 0.25%",
"not dead",
"last 2 versions",
"Firefox ESR"
]
}
Device (CPU + RAM)
@med7atdawoud
@med7atdawoud
navigator.deviceMemory ๐งช
8
> window.navigator.deviceMemory
It returns the approximate device memory in GB
@med7atdawoud
import { createContext, useContext } from 'react';
// Device context to determine strength (simplified example)
const DeviceContext = createContext();
const DeviceProvider = ({ children }) => {
const deviceStrength = navigator.deviceMemory > 2 ? 'strong' : 'weak';
return (
<DeviceContext.Provider value={deviceStrength}>
{children}
</DeviceContext.Provider>
);
};
// Use in a component
const MyComponent = () => {
const deviceStrength = useContext(DeviceContext);
return deviceStrength === 'strong' ? <HeavyFeature /> : <LightFeature />;
};
@med7atdawoud
navigator.hardwareConcurrency
10
> window.navigator.hardwareConcurrency
Returns number of logical processors available to run threads on the user's computer.
@med7atdawoud
if (navigator.hardwareConcurrency) {
const cores = navigator.hardwareConcurrency;
console.log(`This device has ${cores} logical processor cores.`);
if (cores > 4) {
console.log("This device has a high number of cores, enabling advanced features.");
enableHighPerformanceMode();
} else {
console.log("Device has fewer cores, applying optimizations for lower CPU power.");
enableLowPerformanceMode();
}
} else {
console.log("Unable to detect hardware concurrency. Applying default optimizations.");
enableDefaultPerformanceMode();
}
@med7atdawoud
2G
3G
4G
5G
1G
Internet Connection
@med7atdawoud
@med7atdawoud
@med7atdawoud
SSR ?
Use <Form />
Works great without javascript, falls back to HTML form
Network Information APIs ๐งช
{
downlink: 3.85
effectiveType: "4g"
onchange: null
rtt: 50
saveData: false
}
> window.navigator.connection
@med7atdawoud
const networkType = navigator.connection.effectiveType;
if (networkType === '4g') {
// Load heavy assets (like high-quality images or videos)
} else {
// Load lighter assets (like lower-quality images)
}
@med7atdawoud
interface NetworkInformation : EventTarget {
readonly attribute boolean metered;
readonly attribute unrestricted double sustainedSpeed;
attribute EventHandler onchange;
};
UNOFFICIAL (PROPOSAL)
React Adaptive Hooks โ๏ธ
import { useNetworkStatus } from 'react-adaptive-hooks/network';
import { useSaveData } from 'react-adaptive-hooks/save-data';
import { useHardwareConcurrency } from 'react-adaptive-hooks/hardware-concurrency';
export const Func = () => {
const { effectiveConnectionType } = useNetworkStatus();
// effectiveConnectionType can be slow-2G, 3G, 4G
. . .
}
โ Screen Sizes
โ Browsers support
โ Device (CPU + RAM)
โ Internet connection
Recap
@med7atdawoud
Resources
https://www.youtube.com/watch?v=puUPpVrIRkc
https://medium.com/@roderickhsiao/sophisticated-adaptive-loading-strategies-7118341fcf91
https://medium.com/@sushant7/pwa-progressive-web-apps-in-2023-86b04be17508
https://web.dev/adaptive-loading-cds-2019/
https://www.youtube.com/watch?v=BoaORHnJYAE&ab_channel=BeyondFireship
https://addyosmani.com/blog/adaptive-serving/
https://deanhume.com/dynamic-resources-using-the-network-information-api-and-service-workers/
https://justmarkup.com/articles/2017-11-02-network-based-image-loading/
https://developer.mozilla.org/en-US/docs/Glossary/Graceful_degradation
https://www.smashingmagazine.com/2009/04/progressive-enhancement-what-it-is-and-how-to-use-it/
https://developer.mozilla.org/en-US/docs/Glossary/Progressive_Enhancement
Thanks