Joan León PRO
⚡️ Web Performance Consultant | Speaker | Staff Frontend Engineer at @AdevintaSpain | @GoogleDevExpert in #WebPerf | @cloudinary Ambassador
@media (min-width: 50em) {
article {
column-count: 2;
}
}
<img
srcset="image-wide.jpg 600w,
image-ultrawide.jpg 1200w"
sizes="(min-width: 600px) 600w,
(min-width: 1200px) 1200w"
src="image.jpg"
height="300"
width="200"
alt="Awesome image">
window
.matchMedia('(min-width: 768px)')
.matches
import { useMediaQuery } from 'usehooks-ts'
export default function Component() {
const matches = useMediaQuery('(min-width: 768px)')
return (
<div>
{`The view port is
${matches ? 'at least' : 'less than'}
768 pixels wide`}
</div>
)
}
import { useEffect, useState } from 'react'
function useMediaQuery(query: string): boolean {
const getMatches = (query: string): boolean => {
// Prevents SSR issues
if (typeof window !== 'undefined') {
return window.matchMedia(query).matches
}
return false
}
const [matches, setMatches] = useState<boolean>(getMatches(query))
function handleChange() {
setMatches(getMatches(query))
}
useEffect(() => {
const matchMedia = window.matchMedia(query)
// Triggered at the first client-side load and if query changes
handleChange()
// Listen matchMedia
if (matchMedia.addListener) {
matchMedia.addListener(handleChange)
} else {
matchMedia.addEventListener('change', handleChange)
}
return () => {
if (matchMedia.removeListener) {
matchMedia.removeListener(handleChange)
} else {
matchMedia.removeEventListener('change', handleChange)
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [query])
return matches
}
export default useMediaQuery
This property is used to leverage the user's Data Saver preferences.
This property is used to fine-tune data transfer to use less bandwidth.
This property is the CPU core count. It is used to limit costly JavaScript execution and reduce CPU intensive logic when a device can't handle it well.
This property is used to reduce memory consumption on low-end devices.
export default function WebVitalsReporter({...}) {
...
useMount(() => {
const {
deviceMemory,
connection: {effectiveType} = {},
hardwareConcurrency
} = window.navigator || {}
const handleAllChanges = ({attribution, name, rating, value}) => {
...
logger.cwv({
...
...(deviceMemory && {deviceMemory}),
...(effectiveType && {effectiveType}),
...(hardwareConcurrency && {hardwareConcurrency})
})
}
}
}
| Last 7 days
// In the browser
const isSaveDataEnabled = () => {
return navigator.connection?.saveData ?? false;
};
// Use Case
if (isSaveDataEnabled()) {
// Load light component
await import('./LightweightComponent');
} else {
// Load default component
await import('./FullComponent');
}
import { useNetworkStatus } from 'react-adaptive-hooks/network';
import { useSaveData } from 'react-adaptive-hooks/save-data';
import { useHardwareConcurrency } from 'react-adaptive-hooks/hardware-concurrency';
import { useMemoryStatus } from 'react-adaptive-hooks/memory';
import { useMediaCapabilitiesDecodingInfo } from 'react-adaptive-hooks/media-capabilities';
import React from 'react';
import { useNetworkStatus } from 'react-adaptive-hooks/network';
const MyComponent = () => {
const { effectiveConnectionType } = useNetworkStatus();
let media;
switch(effectiveConnectionType) {
case 'slow-2g':
media = <img src='...' alt='low resolution' />;
break;
case '2g':
media = <img src='...' alt='medium resolution' />;
break;
case '3g':
media = <img src='...' alt='high resolution' />;
break;
case '4g':
media = <video muted controls>...</video>;
break;
default:
media = <video muted controls>...</video>;
break;
}
return <div>{media}</div>;
};
import type { EffectiveConnectionType } from '@sbt-web/hooks';
interface Hooks {
saveData?: boolean | null;
effectiveConnectionType?: EffectiveConnectionType | null;
deviceMemory?: number | null;
}
const shouldReduceDataUse = ({
saveData = null,
effectiveConnectionType = null,
deviceMemory = null,
}: Hooks): boolean => {
const saveDataSignal = saveData ?? false;
const ectSignal = effectiveConnectionType ?? '4g';
const deviceMemorySignal = deviceMemory ?? Infinity;
return saveDataSignal || ectSignal !== '4g' || deviceMemorySignal <= 2;
};
export default shouldReduceDataUse;
import VueAdaptiveNetwork from 'vue-adaptive-components/network';
import VueAdaptiveSaveData from 'vue-adaptive-components/save-data';
import VueAdaptiveMemory from 'vue-adaptive-components/hardware-concurrency';
import VueAdaptiveHardwareConcurrency from 'vue-adaptive-components/memory';
<template>
<vue-adaptive-network>
<template v-slot="{ effectiveConnectionType }">
<img v-if="effectiveConnectionType === 'slow-2g'" src='...' alt='low resolution' />
<img v-else-if="effectiveConnectionType === '2g'" src='...' alt='medium resolution' />
<img v-else-if="effectiveConnectionType === '3g'" src='...' alt='high resolution' />
<video v-else-if="effectiveConnectionType === '4g'" muted="" controls="">...</video>
<video v-else="" muted="" controls="">...</video>
</template>
</vue-adaptive-network>
</template>
<script>
import VueAdaptiveNetwork from 'vue-adaptive-components/network'
export default {
components: {
VueAdaptiveNetwork
}
}
</script>
DEPRECATED
<head>
<link rel="preload" as="script" href="critical.js">
</head>
<link rel="preload" href="ComicSans.woff2" as="font" type="font/woff2" crossorigin>
Link: </css/style.css>; rel="preload"; as="style"
import(_/* webpackPreload: true */_ "CriticalChunk")
<script src="script.js">
<script async src="script.js">
<script defer src="script.js">
<script type="module" src="module.mjs">
<script async
defer
src="script.js">
<script type="speculationrules">
{
"prerender": [
{
"urls": ["next.html", "next2.html"]
}
]
}
</script>
Barry Pollard
By Joan León
First, we will talk about adaptive loading, an essential technique in today's online world. Adaptive loading allows your website to adapt to different devices and internet capabilities, ensuring that users don't have to deal with extremely long loading times or performance issues. We will discuss techniques such as image optimization, progressive loading, and methods for evaluating site loading speed on different devices. Next, we will move on to resource loading prioritization, a technique that can truly make a difference in site performance. We will explore how the browser loads resources of a website and how HTML tags can be used to specify the loading priority of each resource. We will also share practical techniques such as loading custom fonts and deferred JavaScript to implement prioritized resource loading. By the end of the talk, you will have the knowledge to apply these techniques to your own projects and take user experience and site performance to the next level. So get ready to enhance your web development skills and create even more impressive websites!