Alistair Shepherd - Front-End Developer
SeriesEight
<img
src="/our-image.jpg"
alt="our image"
>
Source jpeg - 300kB
Webp - 18kB 🙂
JPEG XL* - 12kB 😍
Optimised jpeg - 30kB 😮
AVIF - 14kB 😀
<picture>
<source
media="(-webkit-min-device-pixel-ratio: 1.5)"
srcset="https://example.com/images/our-image_width1200_quality40.jpg 1200w"
sizes="...">
<img
srcset="https://example.com/images/our-image_width600_quality80.jpg 600w"
sizes="..."
alt="">
</picture>
<picture>
<source
type="image/avif"
media="(-webkit-min-device-pixel-ratio: 1.5)"
srcset="/assets/image/otter-300-q40.avif 300w, /assets/image/otter-450-q40.avif 450w, /assets/image/otter-600-q40.avif 600w,
/assets/image/otter-800-q40.avif 800w, /assets/image/otter-1000-q40.avif 1000w, /assets/image/otter-1200-q40.avif 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<source
type="image/avif"
srcset="/assets/image/otter-300-q80.avif 300w, /assets/image/otter-450-q80.avif 450w, /assets/image/otter-600-q80.avif 600w,
/assets/image/otter-800-q80.avif 800w, /assets/image/otter-1000-q80.avif 1000w, /assets/image/otter-1200-q80.avif 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<source
type="image/webp"
media="(-webkit-min-device-pixel-ratio: 1.5)"
srcset="/assets/image/otter-300-q40.webp 300w, /assets/image/otter-450-q40.webp 450w, /assets/image/otter-600-q40.webp 600w,
/assets/image/otter-800-q40.webp 800w, /assets/image/otter-1000-q40.webp 1000w, /assets/image/otter-1200-q40.webp 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<source
type="image/webp"
srcset="/assets/image/otter-300-q80.webp 300w, /assets/image/otter-450-q80.webp 450w, /assets/image/otter-600-q80.webp 600w,
/assets/image/otter-800-q80.webp 800w, /assets/image/otter-1000-q80.webp 1000w, /assets/image/otter-1200-q80.webp 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<source
media="(-webkit-min-device-pixel-ratio: 1.5)"
srcset="/assets/image/otter-300-q40.jpg 300w, /assets/image/otter-450-q40.jpg 450w, /assets/image/otter-600-q40.jpg 600w,
/assets/image/otter-800-q40.jpg 800w, /assets/image/otter-1000-q40.jpg 1000w, /assets/image/otter-1200-q40.jpg 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<img
alt="otter standing on a log looking out majestically"
src="/assets/image/otter-1200-q80.jpg"
srcset="/assets/image/otter-300-q80.jpg 300w, /assets/image/otter-450-q80.jpg 450w,
/assets/image/otter-600-q80.jpg 600w, /assets/image/otter-800-q80.jpg 800w,
/assets/image/otter-1000-q80.jpg 1000w, /assets/image/otter-1200-q80.jpg 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)"
width="1200"
height="784"
loading="lazy"
decoding="async"
>
</picture>
> eleventy-base-blog@5.0.2 build
> eleventy
[...]
Copied 957 files / Wrote 19 files in 188.07 seconds (9898.4ms each, v0.12.1)
3 minutes, 8 seconds!
> eleventy-base-blog@5.0.2 build
> eleventy
[...]
Copied 2 files / Wrote 19 files in 0.59 seconds (31.1ms each, v0.12.1)
✅
✅
❎
❎
and many more
User's browser
Server
HTML
CSS
JS
Images
Images
User's browser
Server
HTML
CSS
JS
Images
Image CDN
Optimised
Images
Source
Server
User's browser
Server
HTML
CSS
JS
Images
Image CDN
Optimised
Images
Source
Media Storage
https://example.imagecdn.com
https://example.imagecdn.com
/https://oursite.com
/images/example.jpg
https://example.imagecdn.com
/images/example.jpg
https://example.imagecdn.com
/images/example.jpg
?w=600&h=400
https://example.imagecdn.com/fetch
/images/example.jpg
/w_600,h_400
.../w_300,h_600,c_thumb,g_auto/...
Tall banner with automatic gravity
.../w_1000,h_400,c_fill,g_north/...
Wide banner anchored to top
<picture>
<source
media="(-webkit-min-device-pixel-ratio: 1.5)"
srcset="
https://example.imagecdn.com/images/w_300,q_40/otter.jpg 300w,
https://example.imagecdn.com/images/w_450,q_40/otter.jpg 450w,
https://example.imagecdn.com/images/w_600,q_40/otter.jpg 600w,
https://example.imagecdn.com/images/w_800,q_40/otter.jpg 800w,
https://example.imagecdn.com/images/w_1000,q_40/otter.jpg 1000w,
https://example.imagecdn.com/images/w_1200,q_40/otter.jpg 1200w"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<img
alt="otter standing on a log looking out majestically"
src="https://example.imagecdn.com/images/w_800,q_80/otter.jpg"
srcset="
https://example.imagecdn.com/images/w_300,q_80/otter.jpg 300w,
https://example.imagecdn.com/images/w_450,q_80/otter.jpg 450w,
https://example.imagecdn.com/images/w_600,q_80/otter.jpg 600w,
https://example.imagecdn.com/images/w_800,q_80/otter.jpg 800w,
https://example.imagecdn.com/images/w_1000,q_80/otter.jpg 1000w,
https://example.imagecdn.com/images/w_1200,q_80/otter.jpg 1200w"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)"
width="1200"
height="784"
loading="lazy"
decoding="async"
>
</picture>
{% image {
name: 'otter.jpg'
alt: 'an otter standing on a log looking majestic'
srcset: [300, 450, 600, 800, 1000, 1200]
sizes: '100vw'
width: 1200
height: 800
loading: 'lazy'
class: 'image-class mb-xl'
} %}
accud.io/imagecdn-11ty
import Image from 'components/Image'
export default function () {
return (
<Image
src="otter.jpg"
alt="an otter standing on a log looking majestic"
srcset={[300, 450, 600, 800, 1000, 1200]}
sizes="100vw"
width="1200"
height="800"
loading="lazy"
className="image-class mb-xl"
/>
)
}
accud.io/imagecdn-react
Not just Jamstack!
cms.1896gallery.com/wp-content/uploads/2019/08/artwork-img.jpg
1896gallery.com/assets/internal-graphic.jpg
Image
CDN
1896gallery.imagecdn.com/wp/artwork-img.jpg
1896gallery.imagecdn.com/assets/internal-graphic.jpg
For very high performing sites different origin has an impact
Easy solution with Netlify
[[redirects]]
from = '/cdn/:image'
to = 'https://example.imagecdn.com/:image'
status = 200
These slides, my sources and helpful links on image CDNs available at accud.io/jamstack-imagecdns
On twitter and most social media @accudio
My website and blog posts alistairshepherd.uk