Browse Source

Links

master
David Larlet 1 month ago
parent
commit
c68de75f20
Signed by: David Larlet <david@larlet.fr> GPG Key ID: 3E2953A359E7E7BD

+ 188
- 0
cache/2024/24716a84007189a332fd8db3e5ff4c05/index.html View File

@@ -0,0 +1,188 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="fr">
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>rêve - Carnets Web de La Grange (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f7f7f7">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
<!-- Is that even respected? Retrospectively? What a shAItshow…
https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
<meta name="robots" content="noai, noimageai">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://www.la-grange.net/2024/02/20/reve">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">


<article>
<header>
<h1>rêve - Carnets Web de La Grange</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://www.la-grange.net/2024/02/20/reve" title="Lien vers le contenu original">Source originale</a>
<br>
Mis en cache le 2024-03-03
</p>
</nav>
<hr>
<figure>
<img src="https://www.la-grange.net/2024/02/15/3433-lune.jpg" alt="Croissant de lune perdu entre les nuages.">
<figcaption>Cupertino, États-Unis, 15 février 2024</figcaption>
</figure>
<blockquote>
<p>Après le Têt, je lui rappellerai que parfos les choses s'accumulent dans la vie sans faire d'édifices.<br>
— Parfum de pagode, Anna Moï, urn:isbn:978-2-7526-0363-0</p>
</blockquote>
<p>Rêve de la nuit dernière :</p>
<p>Je suis un artiste photographe. On me demande une œuvre pour une exposition sur le thème de la photographie et du rapport du spectateur à la photographie dans les expositions de photo. Je prends un appareil photo et une bobine de films de 36 poses dans Tokyo. Je prends des photographies de la ville et de tout ce que les gens imaginent Tokyo être. Une fois la bobine de film terminée, je ne la développe pas. Je laisse les photographies dans la bobine. Je donne la bobine comme objet à exposer dans la gallerie avec les photos de Tokyo à l'intérieur. Le titre est « Tokyo, 19 février 2024 » et c'est tout. Le spectateur ne verra que la bobine et sera en présence d'une série de photographies qui existent mais qu'il ne pourra pas voir.</p>
<hr>
<p><a href="https://www.theguardian.com/world/gallery/2024/feb/20/the-new-rio-queer-communities-under-jair-bolsonaro-in-pictures">The new Rio: queer communities under Jair Bolsonaro</a></p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
</svg> Suivre</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 21
- 0
cache/2024/24716a84007189a332fd8db3e5ff4c05/index.md View File

@@ -0,0 +1,21 @@
title: rêve - Carnets Web de La Grange
url: https://www.la-grange.net/2024/02/20/reve
hash_url: 24716a84007189a332fd8db3e5ff4c05
archive_date: 2024-03-03
og_image: https://www.la-grange.net/2024/02/15/3433-lune.jpg
description:
favicon: https://www.la-grange.net/favicon.ico
language: fr_FR

<figure>
<img src="https://www.la-grange.net/2024/02/15/3433-lune.jpg" alt="Croissant de lune perdu entre les nuages.">
<figcaption>Cupertino, États-Unis, 15 février 2024</figcaption>
</figure>
<blockquote>
<p>Après le Têt, je lui rappellerai que parfos les choses s'accumulent dans la vie sans faire d'édifices.<br>
— Parfum de pagode, Anna Moï, urn:isbn:978-2-7526-0363-0</p>
</blockquote>
<p>Rêve de la nuit dernière :</p>
<p>Je suis un artiste photographe. On me demande une œuvre pour une exposition sur le thème de la photographie et du rapport du spectateur à la photographie dans les expositions de photo. Je prends un appareil photo et une bobine de films de 36 poses dans Tokyo. Je prends des photographies de la ville et de tout ce que les gens imaginent Tokyo être. Une fois la bobine de film terminée, je ne la développe pas. Je laisse les photographies dans la bobine. Je donne la bobine comme objet à exposer dans la gallerie avec les photos de Tokyo à l'intérieur. Le titre est « Tokyo, 19 février 2024 » et c'est tout. Le spectateur ne verra que la bobine et sera en présence d'une série de photographies qui existent mais qu'il ne pourra pas voir.</p>
<hr>
<p><a href="https://www.theguardian.com/world/gallery/2024/feb/20/the-new-rio-queer-communities-under-jair-bolsonaro-in-pictures">The new Rio: queer communities under Jair Bolsonaro</a></p>

+ 184
- 0
cache/2024/4c8a04c4c0e928bd78f22db77425bb47/index.html View File

@@ -0,0 +1,184 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="en">
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>No more forever projects (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f7f7f7">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
<!-- Is that even respected? Retrospectively? What a shAItshow…
https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
<meta name="robots" content="noai, noimageai">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://dianaberlin.com/posts/no-more-forever-projects">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">


<article>
<header>
<h1>No more forever projects</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://dianaberlin.com/posts/no-more-forever-projects" title="Lien vers le contenu original">Source originale</a>
<br>
Mis en cache le 2024-03-03
</p>
</nav>
<hr>
<p>It took me a long time to see past forever projects.</p>
<p>I told myself that making promises gave beginnings gravity. I labeled <a target="_blank" href="https://dianaberlin.com/letters">my newsletter</a> a “lifelong project” not long after I started it. I called <a href="#">/mentoring</a> a “movement” the day I announced it. Commitment marked a project as something worth talking about, I thought. This was how I would give my ideas escape velocity.</p>
<p>Escape velocity came, but at a cost. No amount of attention could spur perpetual motion. Once I’d set every expectation of permanence, disappointment loomed and glowered; inevitable.</p>
<p>Eventually, I started asking myself: <em>why am I promising permanence?</em> The answer crept up on me: <em>because permanence is better than nothing.</em> Without the momentum of obligation, I didn’t trust myself to begin anything in earnest.</p>
<p>The thing is, it never worked. The half-life of obligation is short; the half-life of guilt is long. Promises never saved one of my side projects, but they clogged many nights and weekends with the gunk of regret. Something had to change.</p>
<p>My friend <a target="_blank" href="https://the-pastry-box-project.net/">Jamie Wilkinson</a> once told me about a decision he’d made. <em>No more forever projects</em>, he said. <em>From now on, every project is one-time-only</em><em>. </em>Treat beginnings like endings: celebrate them, document them, let someone else pick up where you leave off. If the project’s worth repeating, there’s nothing to say you can’t still be the standard-bearer. But at least it’s a choice. By ending well, you give yourself the freedom to begin again.</p>
<p>These days, all my projects start as experiments. No forceful promises, no forever projects. Gravity seeps into the things that stick around.</p>
<p><em>Originally published on <a href="https://the-pastry-box-project.net/diana-kimball/2014-march-5">The Pastry Box</a></em></p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
</svg> Suivre</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 10
- 0
cache/2024/4c8a04c4c0e928bd78f22db77425bb47/index.md View File

@@ -0,0 +1,10 @@
title: No more forever projects
url: https://dianaberlin.com/posts/no-more-forever-projects
hash_url: 4c8a04c4c0e928bd78f22db77425bb47
archive_date: 2024-03-03
og_image: http://static1.squarespace.com/static/598927e3bebafbda588a07e2/5989e19437c581cb56aba0e7/59aa233015d5dbe0dac1f149/1504392676284/DKB+Exploded+Logo.png?format=1500w
description: It took me a long time to see past forever projects. I told myself that making promises gave beginnings gravity. I labeled my newsletter &nbsp;a “lifelong project” not long after I started it. I called /mentoring a “movement” the day I announced it. Commitment marked a project as something w
favicon: https://images.squarespace-cdn.com/content/v1/598927e3bebafbda588a07e2/1504459315187-9G9MSVDRY4HEGXNT8JAL/favicon.ico
language: en_US

<p>It took me a long time to see past forever projects.</p><p>I told myself that making promises gave beginnings gravity. I labeled <a target="_blank" href="https://dianaberlin.com/letters">my newsletter</a> a “lifelong project” not long after I started it. I called <a href="#">/mentoring</a> a “movement” the day I announced it. Commitment marked a project as something worth talking about, I thought. This was how I would give my ideas escape velocity.</p><p>Escape velocity came, but at a cost. No amount of attention could spur perpetual motion. Once I’d set every expectation of permanence, disappointment loomed and glowered; inevitable.</p><p>Eventually, I started asking myself: <em>why am I promising permanence?</em> The answer crept up on me: <em>because permanence is better than nothing.</em> Without the momentum of obligation, I didn’t trust myself to begin anything in earnest.</p><p>The thing is, it never worked. The half-life of obligation is short; the half-life of guilt is long. Promises never saved one of my side projects, but they clogged many nights and weekends with the gunk of regret. Something had to change.</p><p>My friend <a target="_blank" href="https://the-pastry-box-project.net/">Jamie Wilkinson</a> once told me about a decision he’d made. <em>No more forever projects</em>, he said. <em>From now on, every project is one-time-only</em><em>. </em>Treat beginnings like endings: celebrate them, document them, let someone else pick up where you leave off. If the project’s worth repeating, there’s nothing to say you can’t still be the standard-bearer. But at least it’s a choice. By ending well, you give yourself the freedom to begin again.</p><p>These days, all my projects start as experiments. No forceful promises, no forever projects. Gravity seeps into the things that stick around.</p><p><em>Originally published on <a href="https://the-pastry-box-project.net/diana-kimball/2014-march-5">The Pastry Box</a></em></p>

+ 360
- 0
cache/2024/6fc45aab6c9584cbb6f55ef70a685d01/index.html View File

@@ -0,0 +1,360 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="fr">
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>Climat : pourquoi les températures battent tous les records depuis la mi-2023 (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f7f7f7">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
<!-- Is that even respected? Retrospectively? What a shAItshow…
https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
<meta name="robots" content="noai, noimageai">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://www.lemonde.fr/les-decodeurs/article/2024/03/03/climat-pourquoi-les-temperatures-battent-tous-les-records-depuis-la-mi-2023_6219806_4355770.html">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">


<article>
<header>
<h1>Climat : pourquoi les températures battent tous les records depuis la mi-2023</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://www.lemonde.fr/les-decodeurs/article/2024/03/03/climat-pourquoi-les-temperatures-battent-tous-les-records-depuis-la-mi-2023_6219806_4355770.html" title="Lien vers le contenu original">Source originale</a>
<br>
Mis en cache le 2024-03-03
</p>
</nav>
<hr>
<p class="article__paragraph article__paragraph--lf">Avec 14,98 °C de moyenne sur l’ensemble du globe,<a href="https://www.lemonde.fr/climat/article/2024/01/09/annee-record-2023-a-ete-plus-chaude-de-1-48-c-que-le-climat-de-l-ere-preindustrielle_6209891_1652612.html"> 2023 est classée comme l’année la plus chaude enregistrée depuis 1850</a>. Et les températures relevées les premières semaines de 2024 suivent la même tendance : du 1<sup>er</sup> janvier au 20 février, la moyenne terrestre affiche + 0,55 °C par rapport à la même période de 2023. Ces niveaux exceptionnels sont le résultat d’une combinaison de facteurs.</p>
<pre><code>
</code></pre>
<div class="multimedia-embed snippet article__media--wide article__media--default">




<div id="d_daily_gmst">
<p class="d_titre d_standard">L'année 2024 est la plus chaude jamais enregistrée</p>
<p class="d_soustitre d_standard">Température moyenne quotidienne à la surface de la Terre depuis 1940.</p>
<div class="d_legende d_standard">
<p class="d_legend_item" data-status="current">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<span></span>
</p>
<p class="d_legend_item" data-status="before">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<span></span>
</p>
<p class="d_legend_item" data-status="mean">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<span>Moyenne 1991-2020</span>
</p>
<p class="d_legend_item" data-status="selected">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<select class="d_select_year">
<option value="default">Choisissez une année</option>
</select>
</p>
</div>


<p class="lmui-chart__source">Sources : <a href="https://cds.climate.copernicus.eu/cdsapp#!/dataset/reanalysis-era5-single-levels" target="_blank">ECMWF (Réanalyses ERA5)</a> via <a href="https://climatereanalyzer.org/clim/t2_daily/?dm_id=world" target="_blank">Climate Reanalyzer</a>
</p>
</div>


</div>
<pre><code>
</code></pre>
<h3 class="article__chapter-title">Le principal coupable : le réchauffement lié aux gaz à effet de serre d’origine humaine</h3>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Les températures exceptionnelles enregistrées sur le globe depuis le début de 2024 sont d’abord la conséquence des émissions de gaz à effet de serre liées aux activités humaines. Depuis 2013, le climat terrestre s’est réchauffé de 0,21 °C en raison des émissions anthropiques, ce qui en fait le principal contributeur à la situation record enregistrée en 2023. <em>« Rien de ce que nous avons vu en 2023 n’aurait été possible sans prendre en compte les gaz à effet de serre émis »</em>, résume Carlo Buontempo, climatologue et directeur du service dévolu au changement climatique au sein du programme de l’Union européenne Copernicus.</p>
<pre><code>
</code></pre>
<h3 class="article__chapter-title">L’invité majeur, anticipé par les climatologues : El Niño</h3>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Le second facteur de réchauffement climatique est le phénomène naturel El Niño, qui revient tous les deux à sept ans. Après deux ans d’événements La Niña, qui, à l’inverse, refroidit légèrement l’atmosphère, El Niño a commencé au printemps 2023, conformément à ce qu’attendaient les scientifiques. Les températures terrestres ont alors décollé, dépassant tous les niveaux enregistrés précédemment.</p>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf"><em>« C’est assez classique. En 2016, c’était pareil. C’est plutôt pendant l’hiver boréal (de novembre à mars) que l’effet d’El Niño sur la température globale est le plus fort »</em>, commente Christophe Cassou, climatologue, directeur de recherche au CNRS et auteur principal du sixième rapport du GIEC (groupe 1). <em>« Depuis quelques années, on était dans une phase plus froide que la normale, liée à une configuration La Niña dans le Pacifique tropical. A partir de juin 2023, on est passé, avec El Niño, dans une configuration chaude de variabilité interne »</em>, confirme Julien Cattiaux, chargé de recherche CNRS au Centre national de recherches météorologiques (CNRM).</p>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">La chaleur des eaux dans l’est de l’océan Pacifique a graduellement augmenté la température de l’atmosphère dans une large zone des tropiques. Finalement, El Niño 2023-2024 a été jugé de force <em>« modérée »</em>. Il a réchauffé le Pacifique tropical et l’Amérique latine d’environ 1,14 °C et la moyenne mondiale de 0,16 °C, soit légèrement plus que ce que l’on observe habituellement (+ 1 °C sur la zone affectée, + 0,1 °C au niveau mondial), mais moins qu’en 2016 (respectivement + 2,12 °C et + 0,17 °C). El Niño a normalement atteint son pic à la fin de 2023 et devrait s’évanouir à la mi-2024, ce qui devrait faire redescendre légèrement la température mondiale moyenne.</p>
<pre><code>
</code></pre>
<div class="multimedia-embed snippet article__media--wide article__media--default">




<div id="d_daily_gsst">
<p class="d_titre d_standard">Les eaux de surface des océans battent des records de température</p>
<p class="d_soustitre d_standard">Température moyenne quotidienne à la surface des océans terrestres depuis 1981.</p>
<div class="d_legende d_standard">
<p class="d_legend_item" data-status="current">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<span></span>
</p>
<p class="d_legend_item" data-status="before">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<span></span>
</p>
<p class="d_legend_item" data-status="mean">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<span>Moyenne 1982-2011</span>
</p>
<p class="d_legend_item" data-status="selected">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<select class="d_select_year">
<option value="default">Choisissez une année</option>
</select>
</p>
</div>


<p class="lmui-chart__source">Sources : <a href="https://cds.climate.copernicus.eu/cdsapp#!/dataset/reanalysis-era5-single-levels" target="_blank">ECMWF (Réanalyses ERA5)</a> via <a href="https://climatereanalyzer.org/clim/t2_daily/?dm_id=world" target="_blank">Climate Reanalyzer</a>
</p>
</div>


</div>
<pre><code>
</code></pre>
<h3 class="article__chapter-title">L’invité surprise : les chaleurs extrêmes dans l’Atlantique Nord</h3>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Si El Niño a été anticipé, ce n’est pas le cas des fortes anomalies de température enregistrées dans l’océan Atlantique Nord depuis l’été 2023. Les scientifiques ont remarqué des canicules marines inédites entre l’été et l’automne 2023, avec des températures qui ont battu très largement les niveaux atteints auparavant sur cette partie de l’océan (plus de 0,5 °C). Du jamais-vu depuis au moins le milieu du XIX<sup>e</sup> siècle.</p>
<pre><code>
</code></pre>
<p id="inread_top-12" class="dfp-slot dfp__slot dfp__inread dfp-unloaded" data-format="inread_top" aria-hidden="true"></p>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Ces chaleurs extrêmes de 2023 ont moins à voir avec le développement d’El Niño qu’avec les conditions anticycloniques de la zone. <em>« On a observé une baisse des vents assez forte sur l’Atlantique Nord</em>, explique Christophe Cassou. <em>Or quand il y a moins de vent, il y a moins d’évaporation, ce qui conduit à un réchauffement des eaux de surface. Ces eaux chauffent aussi car elles se mélangent moins avec les eaux plus profondes et plus froides. »</em></p>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Aujourd’hui, cette configuration météorologique a disparu mais les eaux de surface de l’Atlantique Nord continuent de battre des records de chaleur à cause du phénomène El Niño, qui a fini par réchauffer progressivement les eaux de l’océan pendant l’hiver.</p>
<pre><code>
</code></pre>
<div class="multimedia-embed snippet article__media--wide article__media--default">




<div class="d_dashboard" id="d_daily_nasst">
<p class="d_titre d_standard">Dans l'Atlantique Nord, 2024 est presque un demi-degré au-dessus de toutes les autres années</p>
<p class="d_soustitre d_standard">Température moyenne quotidienne à la surface de l'Atlantique Nord depuis 1981.</p>
<div class="d_legende d_standard">
<p class="d_legend_item" data-status="current">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<span></span>
</p>
<p class="d_legend_item" data-status="before">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<span></span>
</p>
<p class="d_legend_item" data-status="mean">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<span>Moyenne 1982-2011</span>
</p>
<p class="d_legend_item" data-status="selected">
<svg><line x1="0" y1="5" x2="14" y2="5"></line></svg>
<select class="d_select_year">
<option value="default">Choisissez une année</option>
</select>
</p>
</div>


<p class="lmui-chart__source">Sources : <a href="https://cds.climate.copernicus.eu/cdsapp#!/dataset/reanalysis-era5-single-levels" target="_blank">ECMWF (Réanalyses ERA5)</a> via <a href="https://climatereanalyzer.org/clim/t2_daily/?dm_id=world" target="_blank">Climate Reanalyzer</a>
</p>
</div>


</div>
<pre><code>
</code></pre>
<h3 class="article__chapter-title">Les facteurs naturels additionnels : le cycle solaire et l’éruption du Hunga Tonga</h3>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Plusieurs autres phénomènes ont contribué à pousser un peu plus haut les températures depuis l’été 2023. L’activité du soleil d’abord. Ce dernier entre progressivement dans son pic jusqu’à la mi-2025. Il accroît temporairement et légèrement l’intensité du rayonnement reçu par la Terre. Ce phénomène fait partie du cycle solaire, qui dure environ onze ans. <em>« Le pic solaire joue de manière marginale mais c’est encore un petit incrément »</em>, commente Christophe Cassou.</p>
<pre><code>
</code></pre>
<p id="inread-17" class="dfp-slot dfp__slot dfp__inread dfp-unloaded" data-format="inread" aria-hidden="true"></p>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Autre facteur de réchauffement : <a href="https://www.lemonde.fr/sciences/article/2022/09/20/le-volcan-hunga-tonga-a-l-origine-d-un-tsunami-hors-norme_6142449_1650684.html">l’éruption du volcan Hunga Tonga, dans le Pacifique, en janvier 2022</a>. Les éruptions volcaniques ont habituellement un effet refroidissant sur le climat, en raison de la grande quantité d’aérosols qu’elles projettent dans l’atmosphère. Une fois en suspension, les particules fines réfléchissent les rayons du soleil et font chuter les températures. Cependant le Hunga Tonga a la particularité d’être un volcan sous-marin. De ce fait, il a essentiellement envoyé de la vapeur d’eau à de très hautes altitudes et en grande quantité (environ 150 millions de tonnes). Cette vapeur a un effet de serre très faible lorsqu’elle est située dans les couches basses de l’atmosphère (à moins de 10 km d’altitude), car au gré des vents et du cycle de l’eau, elle se condense naturellement et finit par retomber au sol. A l’inverse, lorsqu’elle est envoyée dans la stratosphère, elle y persiste beaucoup plus longtemps et finit par avoir un léger pouvoir réchauffant.</p>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Dans les facteurs réchauffants, on peut également citer le déclin spectaculaire subi par la banquise dans l’Antarctique depuis plus d’un an, avec un maximum enregistré le 10 septembre à 16,96 millions de kilomètres carrés, soit un déclin de 8,8 % par rapport à la médiane 1981-2010. La fonte de la glace de mer affecte la circulation des eaux océaniques et contribue à réduire la quantité d’énergie solaire que renvoie la surface terrestre.</p>
<pre><code>
</code></pre>
<h2 class="article__sub-title">2023, le résultat d’une combinaison de facteurs</h2>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">L’année 2023 a largement battu le record de chaleur détenu avant elle par l’année 2016 (+ 0,17 °C), frappée par un phénomène El Niño particulièrement fort.<em> « On n’est pas surpris en tant que tel</em>, nuance Christophe Cassou<em>. Le saut de températures a pu être surprenant pour certains mois en 2023, comme en septembre, où on a battu des records de manière très significative. Mais on n’est pas sorti du domaine des possibles des modèles</em> <em>climatiques en moyenne sur une année. »</em></p>
<pre><code>
</code></pre>
<figure class="article__media article__media--default "> <img src="" data-srcset=" https://img.lemde.fr/2024/02/29/0/0/1024/564/630/0/75/0/a970074_1709217655610-forcingsummary2023-1024x564.png 1x, https://img.lemde.fr/2024/02/29/0/0/1024/564/1260/0/45/0/a970074_1709217655610-forcingsummary2023-1024x564.png 2x" alt="Les facteurs du réchauffement climatique des dix dernières années établis par Berkeley Earth, une organisation américaine à but non lucratif. Le réchauffement d’origine anthropique est responsable de la majorité du réchauffement en 2023, mais El Niño a également eu un effet très net. Le cycle solaire, l’éruption du Hunga Tonga et la réduction de la pollution atmosphérique d’origine maritime ont également pu jouer un petit rôle dans les records de 2023."> <noscript><img src="https://img.lemde.fr/2024/02/29/0/0/1024/564/630/0/75/0/a970074_1709217655610-forcingsummary2023-1024x564.png" alt="Les facteurs du réchauffement climatique des dix dernières années établis par Berkeley Earth, une organisation américaine à but non lucratif. Le réchauffement d’origine anthropique est responsable de la majorité du réchauffement en 2023, mais El Niño a également eu un effet très net. Le cycle solaire, l’éruption du Hunga Tonga et la réduction de la pollution atmosphérique d’origine maritime ont également pu jouer un petit rôle dans les records de 2023."></noscript> <figcaption class="article__legend" aria-hidden="true">Les facteurs du réchauffement climatique des dix dernières années établis par Berkeley Earth, une organisation américaine à but non lucratif. Le réchauffement d’origine anthropique est responsable de la majorité du réchauffement en 2023, mais El Niño a également eu un effet très net. Le cycle solaire, l’éruption du Hunga Tonga et la réduction de la pollution atmosphérique d’origine maritime ont également pu jouer un petit rôle dans les records de 2023. <span class="article__credit" aria-hidden="true">BERKELEY EARTH</span> </figcaption> </figure>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Ce qui a pu en revanche davantage surprendre la communauté scientifique, ce sont les marges très importantes avec lesquelles les records ont été battus. L’année 2023 a connu ce que les anglophones appellent des <em>record-shattering events</em>, des événements climatiques qui « fracassent » les précédents records. Le réchauffement climatique serait-il en train d’accélérer plus vite que ne l’ont prévu les modélisations scientifiques ? La question est prudemment posée par les climatologues.</p>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf"><em>« Il y a des observations émergentes dans la littérature</em> <em>scientifique qui suggèrent une accélération du réchauffement climatique au moins en termes d’<a href="https://www.lemonde.fr/les-decodeurs/article/2021/11/03/comment-l-homme-bouscule-l-equilibre-du-climat-sur-la-terre_6100746_4355770.html">équilibre radiatif</a> </em>[la différence entre l’énergie reçue et l’énergie perdue dans l’espace par la Terre], expose Carlo Buontempo.<em> Donc la possibilité de voir une accélération du réchauffement en termes de températures n’est pas exclue. »</em> Pour l’heure, l’idée ne fait cependant pas consensus. <em>« Le caractère simultané d’événements chauds en différents endroits du globe ne remet pas forcément en cause toutes les estimations qui ont été faites du rythme du réchauffement actuel, et de ce qu’il sera dans les décennies à venir »</em>, temporise Aurélien Ribes, chercheur au Centre national de la recherche météorologique.</p>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Même si elles sont dans la fourchette haute, les températures de 2023 et de 2024 restent cohérentes avec les projections des modèles climatiques. <em>« Il y a une tendance de long terme relativement bien estimée et, par-dessus, il y a la variabilité interne qui fait son œuvre et qui de temps en temps va générer des records qui sont nettement au-dessus de ce qu’on a vu précédemment »</em>, explique Aurélien Ribes.</p>
<pre><code>
</code></pre>
<p class="article__paragraph article__paragraph--lf">Et même s’il n’accélère pas, le rythme actuel du réchauffement est déjà suffisamment rapide pour que des années « normales » battent à leur tour 2023 d’ici quelques années seulement.<em> « En sept ans, le climat s’est déjà tellement réchauffé que 2023 aurait battu le record de 2016 même si ça avait été une année normale, sans El Niño »</em>, illustre Julien Cattiaux.</p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
</svg> Suivre</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 115
- 0
cache/2024/6fc45aab6c9584cbb6f55ef70a685d01/index.md
File diff suppressed because it is too large
View File


+ 219
- 0
cache/2024/a122504621c3c5318c0bdee38ef4479b/index.html View File

@@ -0,0 +1,219 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="en">
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>Capo.js: A five minute web performance boost (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f7f7f7">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
<!-- Is that even respected? Retrospectively? What a shAItshow…
https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
<meta name="robots" content="noai, noimageai">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://frontendmasters.com/blog/capo-js-a-five-minute-web-performance-boost/">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">


<article>
<header>
<h1>Capo.js: A five minute web performance boost</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://frontendmasters.com/blog/capo-js-a-five-minute-web-performance-boost/" title="Lien vers le contenu original">Source originale</a>
<br>
Mis en cache le 2024-03-03
</p>
</nav>
<hr>
<p>You want a quick web performance win at work that’s sure to get you a promotion? Want it to only take five minutes? Then I got you.</p>

<figure class="wp-block-image size-full"><img decoding="async" src="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/Untitled.png?resize=519%2C97&amp;ssl=1" alt="Screenshot of the Capo.js console output showing rows of colored rectangles for the Actual order and Sorted order of elements in the head." class="wp-image-1090" srcset="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/Untitled.png?w=519&amp;ssl=1 519w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/Untitled.png?resize=300%2C56&amp;ssl=1 300w" sizes="(max-width: 519px) 100vw, 519px" data-recalc-dims="1"></figure>

<p><a href="https://rviscomi.github.io/capo.js/">Capo.js</a> is a tool to get your <code>&lt;head&gt;</code> in order. It’s based on some <a href="https://csswizardry.com/ct/">research by Harry Roberts</a> that shows how something seemingly insignificant as the elements in your <code>&lt;head&gt;</code> tag can make your page load up to 7 seconds slower! From pragma directives, to async scripts, to stylesheets, to open graph tags, it’s easy to mess up and can have consequences. Capo.js will show you the <a href="https://rviscomi.github.io/capo.js/user/rules/">specific order of elements</a> to make your <code>&lt;head&gt;</code> and your page a little (or a lotta) bit faster.</p>

<h2 class="wp-block-heading" id="toc-1"><a href="#usage" aria-hidden="true" class="aal_anchor" id="usage"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Usage</h2>

<ol>
<li>Head over to <a href="https://rviscomi.github.io/capo.js/">Capo.js homepage</a></li>



<li>Install the <a href="https://chromewebstore.google.com/detail/capo-get-your-%EF%B9%A4%F0%9D%9A%91%F0%9D%9A%8E%F0%9D%9A%8A%F0%9D%9A%8D%EF%B9%A5/ohabpnaccigjhkkebjofhpmebofgpbeb">Capo.js Chrome Extension</a> (you can also use it as a DevTools Snippet or bookmarklet)</li>



<li>Run Capo.js</li>
</ol>

<p>Capo.js will log two colored bar charts in your JS console; your “Actual” <code>&lt;head&gt;</code> order and a “Sorted” <code>&lt;head&gt;</code> order. You can expand each chart to see more details. If you see a big gray bar in the middle of your “Actual” bar chart, then you’re leaving some quick wins on the table. The “Sorted” dropdown will show you the corrected order and even give you the code. But in the real world you probably need to futz with a layout template or your <code>_header.php</code> to get it reorganized.</p>

<p>Installing Capo.js takes about a minute, rearranging your <code>&lt;head&gt;</code> takes another minute. Honestly the longest part is making the Pull Request.</p>

<h2 class="wp-block-heading" id="toc-2"><a href="#editor-intervention" aria-hidden="true" class="aal_anchor" id="editor-intervention"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EDITOR INTERVENTION</h2>

<p>[Chris busts through the door.]</p>

<p>OK fine Dave, I’ll give it a shot right here on Boost itself. </p>

<p>I installed the Chrome Extension and ran it and got this little popup:</p>

<figure class="wp-block-image size-large"><img decoding="async" src="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?resize=1024%2C187&amp;ssl=1" alt='"Before" sort order, scattered rectangles of various colors' class="wp-image-1095" srcset="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?resize=1024%2C187&amp;ssl=1 1024w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?resize=300%2C55&amp;ssl=1 300w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?resize=768%2C140&amp;ssl=1 768w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?w=1272&amp;ssl=1 1272w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1"></figure>

<p> At first I was a little confused, like this was some fancy code that Web Perf people immediately understand but I was out of the loop on. But actually it’s just a visualization of the order of things (top: actual, bottom: ideal). As a little UX feedback, it should say “Open your console for more information” because that’s where all the useful stuff is. </p>

<p>I found it most useful to look at the “Sorted” output (which is what you <em>should</em> be doing) and then try to get my source code to match that. I think I generally did OK:</p>

<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" src="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?resize=1024%2C194&amp;ssl=1" alt='"After" sort order, scattered rectangles of various colors, slightly less scattered than the previous image' class="wp-image-1096" srcset="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?resize=1024%2C194&amp;ssl=1 1024w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?resize=300%2C57&amp;ssl=1 300w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?resize=768%2C146&amp;ssl=1 768w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?w=1298&amp;ssl=1 1298w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1"></figure>

<p>I wasn’t able to get it perfect because of WordPress. A decent chunk of what goes into your <code>&lt;head&gt;</code> in WordPress comes from the output of the <code>&lt;php wp_head(); ?&gt;</code> function. I’m sure it’s technically possible to re-order output in there, but that was a more effort that I felt was worth it right at this minute.</p>

<p>Take your wins, that’s what I always say.</p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
</svg> Suivre</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 84
- 0
cache/2024/a122504621c3c5318c0bdee38ef4479b/index.md View File

@@ -0,0 +1,84 @@
title: Capo.js: A five minute web performance boost
url: https://frontendmasters.com/blog/capo-js-a-five-minute-web-performance-boost/
hash_url: a122504621c3c5318c0bdee38ef4479b
archive_date: 2024-03-03
og_image: https://frontendmasters.com/blog/wp-json/social-image-generator/v1/image/1086
description: You want a quick web performance win at work that’s sure to get you a promotion? Want it to only take five minutes? Then I got you. Capo.js is a tool to get your <head> in order. It’s based o…
favicon: https://frontendmasters.com/favicon-32x32.png
language: en_US
<p>You want a quick web performance win at work that’s sure to get you a promotion? Want it to only take five minutes? Then I got you.</p>



<figure class="wp-block-image size-full"><img decoding="async" src="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/Untitled.png?resize=519%2C97&amp;ssl=1" alt="Screenshot of the Capo.js console output showing rows of colored rectangles for the Actual order and Sorted order of elements in the head." class="wp-image-1090" srcset="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/Untitled.png?w=519&amp;ssl=1 519w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/Untitled.png?resize=300%2C56&amp;ssl=1 300w" sizes="(max-width: 519px) 100vw, 519px" data-recalc-dims="1"></figure>



<p><a href="https://rviscomi.github.io/capo.js/">Capo.js</a> is a tool to get your <code>&lt;head&gt;</code> in order. It’s based on some <a href="https://csswizardry.com/ct/">research by Harry Roberts</a> that shows how something seemingly insignificant as the elements in your <code>&lt;head&gt;</code> tag can make your page load up to 7 seconds slower! From pragma directives, to async scripts, to stylesheets, to open graph tags, it’s easy to mess up and can have consequences. Capo.js will show you the <a href="https://rviscomi.github.io/capo.js/user/rules/">specific order of elements</a> to make your <code>&lt;head&gt;</code> and your page a little (or a lotta) bit faster.</p>



<h2 class="wp-block-heading" id="toc-1"><a href="#usage" aria-hidden="true" class="aal_anchor" id="usage"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Usage</h2>



<ol>
<li>Head over to <a href="https://rviscomi.github.io/capo.js/">Capo.js homepage</a></li>



<li>Install the <a href="https://chromewebstore.google.com/detail/capo-get-your-%EF%B9%A4%F0%9D%9A%91%F0%9D%9A%8E%F0%9D%9A%8A%F0%9D%9A%8D%EF%B9%A5/ohabpnaccigjhkkebjofhpmebofgpbeb">Capo.js Chrome Extension</a> (you can also use it as a DevTools Snippet or bookmarklet)</li>



<li>Run Capo.js</li>
</ol>



<p>Capo.js will log two colored bar charts in your JS console; your “Actual” <code>&lt;head&gt;</code> order and a “Sorted” <code>&lt;head&gt;</code> order. You can expand each chart to see more details. If you see a big gray bar in the middle of your “Actual” bar chart, then you’re leaving some quick wins on the table. The “Sorted” dropdown will show you the corrected order and even give you the code. But in the real world you probably need to futz with a layout template or your <code>_header.php</code> to get it reorganized.</p>



<p>Installing Capo.js takes about a minute, rearranging your <code>&lt;head&gt;</code> takes another minute. Honestly the longest part is making the Pull Request.</p>



<h2 class="wp-block-heading" id="toc-2"><a href="#editor-intervention" aria-hidden="true" class="aal_anchor" id="editor-intervention"><svg aria-hidden="true" class="aal_svg" version="1.1" viewbox="0 0 16 16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>EDITOR INTERVENTION</h2>



<p>[Chris busts through the door.]</p>



<p>OK fine Dave, I’ll give it a shot right here on Boost itself. </p>



<p>I installed the Chrome Extension and ran it and got this little popup:</p>



<figure class="wp-block-image size-large"><img decoding="async" src="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?resize=1024%2C187&amp;ssl=1" alt='"Before" sort order, scattered rectangles of various colors' class="wp-image-1095" srcset="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?resize=1024%2C187&amp;ssl=1 1024w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?resize=300%2C55&amp;ssl=1 300w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?resize=768%2C140&amp;ssl=1 768w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/before.png?w=1272&amp;ssl=1 1272w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1"></figure>



<p> At first I was a little confused, like this was some fancy code that Web Perf people immediately understand but I was out of the loop on. But actually it’s just a visualization of the order of things (top: actual, bottom: ideal). As a little UX feedback, it should say “Open your console for more information” because that’s where all the useful stuff is. </p>



<p>I found it most useful to look at the “Sorted” output (which is what you <em>should</em> be doing) and then try to get my source code to match that. I think I generally did OK:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" src="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?resize=1024%2C194&amp;ssl=1" alt='"After" sort order, scattered rectangles of various colors, slightly less scattered than the previous image' class="wp-image-1096" srcset="https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?resize=1024%2C194&amp;ssl=1 1024w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?resize=300%2C57&amp;ssl=1 300w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?resize=768%2C146&amp;ssl=1 768w, https://i0.wp.com/frontendmasters.com/blog/wp-content/uploads/2024/02/after.png?w=1298&amp;ssl=1 1298w" sizes="(max-width: 1000px) 100vw, 1000px" data-recalc-dims="1"></figure>



<p>I wasn’t able to get it perfect because of WordPress. A decent chunk of what goes into your <code>&lt;head&gt;</code> in WordPress comes from the output of the <code>&lt;php wp_head(); ?&gt;</code> function. I’m sure it’s technically possible to re-order output in there, but that was a more effort that I felt was worth it right at this minute.</p>



<p>Take your wins, that’s what I always say.</p>

+ 381
- 0
cache/2024/ad911ebf7ba5523ef0be1bdd599f7623/index.html View File

@@ -0,0 +1,381 @@
<!doctype html><!-- This is a valid HTML5 document. -->
<!-- Screen readers, SEO, extensions and so on. -->
<html lang="en">
<!-- Has to be within the first 1024 bytes, hence before the `title` element
See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
<meta charset="utf-8">
<!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
<!-- The viewport meta is quite crowded and we are responsible for that.
See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
<meta name="viewport" content="width=device-width,initial-scale=1">
<!-- Required to make a valid HTML5 document. -->
<title>JavaScript Bloat in 2024 (archive) — David Larlet</title>
<meta name="description" content="Publication mise en cache pour en conserver une trace.">
<!-- That good ol' feed, subscribe :). -->
<link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
<!-- Generated from https://realfavicongenerator.net/ such a mess. -->
<link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
<link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
<link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
<link rel="manifest" href="/static/david/icons2/site.webmanifest">
<link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
<link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
<meta name="msapplication-TileColor" content="#f7f7f7">
<meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
<meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
<!-- Is that even respected? Retrospectively? What a shAItshow…
https://neil-clarke.com/block-the-bots-that-feed-ai-models-by-scraping-your-website/ -->
<meta name="robots" content="noai, noimageai">
<!-- Documented, feel free to shoot an email. -->
<link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
<!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t4_poly_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: light), (prefers-color-scheme: no-preference)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
<script>
function toggleTheme(themeName) {
document.documentElement.classList.toggle(
'forced-dark',
themeName === 'dark'
)
document.documentElement.classList.toggle(
'forced-light',
themeName === 'light'
)
}
const selectedTheme = localStorage.getItem('theme')
if (selectedTheme !== 'undefined') {
toggleTheme(selectedTheme)
}
</script>

<meta name="robots" content="noindex, nofollow">
<meta content="origin-when-cross-origin" name="referrer">
<!-- Canonical URL for SEO purposes -->
<link rel="canonical" href="https://tonsky.me/blog/js-bloat/">

<body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">


<article>
<header>
<h1>JavaScript Bloat in 2024</h1>
</header>
<nav>
<p class="center">
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="https://tonsky.me/blog/js-bloat/" title="Lien vers le contenu original">Source originale</a>
<br>
Mis en cache le 2024-03-03
</p>
</nav>
<hr>
<p><em>Translations: <a href="https://habr.com/ru/companies/ruvds/articles/796595/" target="_blank">Russian</a></em></p>
<p>I was a bit out of touch with modern front-end development. I also remembered articles about web bloat, how the average web page size was approaching several megabytes!</p>
<p>So all this time I was living under impression that, for example, if the average web page size is 3 MB, then JavaScript bundle should be around 1 MB. Surely content should still take the majority, no?</p>
<p>Well, the only way to find out is to fuck around. Let’s do a reality check!</p>
<p>I’m writing this in 2024, so maybe do a sequel in a few years?</p>
<h1 id="method">Method</h1>
<ul>
<li>Firefox on macOS (but should be the same in any browser)</li>
<li>Not incognito (I want to see numbers <em>inside</em> the app, and there’s a better chance it will resemble actual everyday experience)</li>
<li>All extensions disabled</li>
<li>JavaScript only</li>
<li>Uncompressed</li>
<li>Service Workers enabled (again, more real-life)</li>
<li>All caching disabled (cold load)</li>
</ul>
<p>Why only JavaScript? Content varies a lot from site to site (surely videos on YouTube are heavier than text messages on Slack), but JavaScript is a universal metric for “complexity of interactions”.</p>
<p>The main goal is to evaluate how much work the browser has to do to parse and execute code.</p>
<p>To set some baseline, let’s start with this blog:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/tonsky@2x.webp?t=1709315366"> </figure>
<p>The number here would be 0.004 MB. I also highlighted all the important bits you need to set if you decide to reproduce this at home.</p>
<h1 id="landings">Landings</h1>
<p>Okay, let’s start with something simple, like landing pages/non-interactive apps.</p>
<p>A normal slightly interactive page looks like this — Wikipedia, 0.2 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/wikipedia@2x.webp?t=1709315366"> </figure>
<p>Slightly bloated — like this — Linear, 3 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/linear@2x.webp?t=1709315366"> </figure>
<p>Remember: that’s without images, or videos, or even styles! Just JS code.</p>
<p>A bad landing page looks like this — Zoom, 6 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/zoom@2x.webp?t=1709315366"> </figure>
<p>or like Vercel, 6 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/vercel@2x.webp?t=1709315366"> </figure>
<p>Yes, this is just a landing page. No app, no functionality, no calls. 6 MB of JavaScript just for that.</p>
<p>You can do a lot worse, though — Gitlab, 13 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/gitlab@2x.webp?t=1709315366"> </figure>
<p>Still just the landing.</p>
<h1 id="mostly-static-websites">Mostly static websites</h1>
<p>Nothing simpler than showing a static wall of text. Medium needs 3 MB just to do that:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/medium@2x.webp?t=1709315366"> </figure>
<p>Substack needs 4 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/substack@2x.webp?t=1709315366"> </figure>
<p>Progress?</p>
<p>Quora, 4.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/quora@2x.webp?t=1709315366"> </figure>
<p>Pinterest, 10 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/pinterest@2x.webp?t=1709315366"> </figure>
<p>Patreon, 11 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/patreon@2x.webp?t=1709315366"> </figure>
<p>And all this could’ve been a static page...</p>
<h1 id="search">Search</h1>
<p>When your app’s interactivity is limited to mostly search. Type the query — show the list of results. How heavy is that?</p>
<p>StackOverflow, 3.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/stackoverflow@2x.webp?t=1709315366"> </figure>
<p>NPM, 4 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/npmjs@2x.webp?t=1709315366"> </figure>
<p>Airbnb, 7 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/airbnb@2x.webp?t=1709315366"> </figure>
<p>Booking.com, 12 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/booking@2x.webp?t=1709315366"> </figure>
<p>But Niki, booking is complicated! Look at all this UI! All these filters. All these popups about people near you stealing your vacation!</p>
<p>Okay, okay. Something simpler then. Google. How about Google? One text field, list of links. Right?</p>
<p>Well, it’ll cost you whooping 9 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/google@2x.webp?t=1709315366"> </figure>
<p>Just to show a list of links.</p>
<h1 id="simple-one-interaction-apps">Simple one-interaction apps</h1>
<p>Google Translate is just two text boxes. For that, you need 2.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/google_translate@2x.webp?t=1709315366"> </figure>
<p>ChatGPT is <em>one</em> text box. 7 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/openai@2x.webp?t=1709315366"> </figure>
<p>I mean, surely, ChatGPT is complex. But on the server, not in the browser!</p>
<h1 id="videos">Videos</h1>
<p>Loom — 7 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/loom@2x.webp?t=1709315366"> </figure>
<p>YouTube — 12 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/youtube@2x.webp?t=1709315366"> </figure>
<p>Compare it to people who really care about performance — Pornhub, 1.4 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/pornhub@2x.webp?t=1709315366"> </figure>
<h1 id="audio">Audio</h1>
<p>I guess audio just requires 12 MB no matter what:</p>
<p>SoundCloud:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/soundcloud@2x.webp?t=1709315366"> </figure>
<p>Spotify:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/spotify@2x.webp?t=1709315366"> </figure>
<h1 id="email">Email</h1>
<p>Okay, video and audio are probably heavy stuff (even though we are not measuring content, just JS, remember!). Let’s move to simpler office tasks.</p>
<p>Google Mail is just (just!) 20 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/gmail@2x.webp?t=1709315366"> </figure>
<p>It’s a freaking mailbox!!! How on earth is it almost as big as Figma, who ships entire custom C++/OpenGL rendering for their app?</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/figma@2x.webp?t=1709315366"> </figure>
<p>And if you are thinking: mail is complicated, too. Lots of UI, lots of interactivity. Maybe 20 MB is okay?</p>
<p>No!</p>
<p>Just no. See, FastMail, same deal, but only 2 MB. 10× less!</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/fastmail@2x.webp?t=1709315366"> </figure>
<h1 id="productivity">Productivity</h1>
<p>Okay, maybe e-mail is too complicated? How about something even simpler? Like a TODO list?</p>
<p>Well, meet Todoist, 9 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/todoist@2x.webp?t=1709315366"> </figure>
<p>Showing you a list of files in folders requires 10 MB in Dropbox:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/dropbox@2x.webp?t=1709315366"> </figure>
<p>List of passwords? That’ll be 13 MB on 1Password:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/1password@2x.webp?t=1709315366"> </figure>
<p>Cards? Add 0.5 MB more, up to 13.5 MB. Trello:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/trello@2x.webp?t=1709315366"> </figure>
<p>Okay, maybe TODO lists are too complex, too? How about chatting?</p>
<p>Well, Discord needs 21 MB to do that:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/discord@2x.webp?t=1709315366"> </figure>
<h1 id="document-editing">Document editing</h1>
<p>Okay, document editing is hard, right? You have to implement cursor movement, synchronization, etc.</p>
<p>Google Docs, 13.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/google_docs@2x.webp?t=1709315366"> </figure>
<p>Something simpler? Notion, 16 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/notion@2x.webp?t=1709315366"> </figure>
<h1 id="social-networks">Social Networks</h1>
<p>The typical size of code that social networks need for like buttons to go brrr is 12 MB.</p>
<p>Twitter, 11 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/twitter@2x.webp?t=1709315366"> </figure>
<p>Facebook, 12 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/facebook@2x.webp?t=1709315366"> </figure>
<p>TikTok, 12.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/tiktok@2x.webp?t=1709315366"> </figure>
<p>Instagram is somehow bigger than Facebook, despite having like 10× less functions. 16 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/instagram@2x.webp?t=1709315366"> </figure>
<p>LinkedIn. Is it a blog? A platform? It has search, it has messaging, it has social functions. Anyways, that’ll be 31 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/linkedin@2x.webp?t=1709315366"> </figure>
<p>By the way, I'd like to add you to my professional network on LinkedIn.</p>
<h1 id="elephants--its-own-category">Elephants — its own category</h1>
<p>Sometimes websites are so stupidly, absurdly large that they deserve their own category.</p>
<p>Here, Jira, a task management software. Almost 50 MB!</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/jira@2x.webp?t=1709315366"> </figure>
<p>Do they ship the entire Electron compiled WASM or what?</p>
<p>But that’s not the limit! Slack adds 5 more MB, up to 55 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/slack@2x.webp?t=1709315366"> </figure>
<p>Yes, it’s a chat. You know, list of users, messages, reactions. Stuff we did on raw HTML, even before JS was invented?</p>
<p>That’s 55 MB in today’s world. It’s almost like they are trying to see how much more bullshit can they put in a browser before it breaks.</p>
<p>Finally, this blew my mind. Somehow <a href="https://react.dev/blog/2023/03/16/introducing-react-dev" target="_blank">react.dev</a> starts with a modest 2 MB but as you scroll back and forth, it grows indefinitely. Just for fun, I got it to 100 MB (of JavaScript!), but you can go as far as you like:</p>
<figure>
<video autoplay="" muted="" loop="" preload="auto" playsinline="" controls="">
<source src="https://tonsky.me/blog/js-bloat/react@2x.mp4?t=1708621056" type="video/mp4">
</source></video>
</figure>
<p>What is going on there? Even if it unloads and downloads parts of that blog post, how is it growing so quickly? The text itself is probably only 50 KB (0.05 MB).</p>
<p>UPD: It has been brought to my attention that this behavior is not, in fact, representative of normal user experience. Normally embedded code editors will be cached after first load and subsequent loads will be served from disk cache. So as you scroll, you will see no network traffic, but these 100 MB of JS will still be parsed, evaluated and initialized over and over as you scroll.</p>
<h1 id="how-fast-are-we-degrading">How fast are we degrading?</h1>
<p>Look how cute! In 2015 average web page size was approaching shareware version of Doom 1 (2.5 MB):</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/bloat_2015@2x.webp?t=1709315366"><figcaption><a href="https://twitter.com/xbs/status/626781529054834688" target="_blank">Source</a></figcaption> </figure>
<p>Well, in 2024, Slack pulls up 55 MB, the size of the original Quake 1 with all the resources. But now it’s just in JavaScript alone.</p>
<p>For a chat app!</p>
<h1 id="how-big-is-10-mb-anyway">How big is 10 MB anyway?</h1>
<p>To be honest, after typing all these numbers, 10 MB doesn’t even feel that big or special. Seems like shipping 10 MB of <em>code</em> is normal now.</p>
<p>If we assume that the average code line is about 65 characters, that would mean we are shipping ~150,000 lines of code. With every website! Sometimes just to show static content!</p>
<p>And that code is minified already. So it’s more like 300K+ LoC just for one website.</p>
<p>But are modern websites really <em>that</em> complex? The poster child of SPAs, Google Maps, is quite modest by modern standards — is <em>still</em> just 4.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/google_maps@2x.webp?t=1709315366"> </figure>
<p>Somebody at Google is seriously falling behind. Written with modern front-end technologies, it should be at least 20 MB.</p>
<p>And if you, like me, thought that “Figma is a really complex front-end app, so it must have a huge javascript download size”, well, that’s correct, but then Gmail is about as complex as Figma, LinkedIn is 1.5× more complex and Slack is 2.5× more ¯\_(ツ)_/¯</p>
<h1 id="conclusion">Conclusion</h1>
<p>It’s not just about download sizes. I welcome high-speed internet as much as the next guy. But code — JavaScript — is something that your browser has to parse, keep in memory, execute. It’s not free. And these people talk about performance and battery life...</p>
<p>Call me old-fashioned, but I firmly believe content should outweigh code size. If you are writing a blog post for 10K characters, you don’t need 1000× more JavaScript to render it.</p>
<p>This site is doing it right:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/jquery@2x.webp?t=1709315366"> </figure>
<p>That’s 0.1 MB. And that’s enough!</p>
<p>And yet, on the same internet, in the same timeline, Gitlab needs 13 MB of code, 500K+ LoC of JS, just to display a static landing page.</p>
<p>Fuck me.</p>
</article>


<hr>

<footer>
<p>
<a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
</svg> Accueil</a> •
<a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
</svg> Suivre</a> •
<a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
</svg> Pro</a> •
<a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
</svg> Email</a> •
<abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
</svg> Légal</abbr>
</p>
<template id="theme-selector">
<form>
<fieldset>
<legend><svg class="icon icon-brightness-contrast">
<use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
</svg> Thème</legend>
<label>
<input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
</label>
<label>
<input type="radio" value="dark" name="chosen-color-scheme"> Foncé
</label>
<label>
<input type="radio" value="light" name="chosen-color-scheme"> Clair
</label>
</fieldset>
</form>
</template>
</footer>
<script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
<script>
function loadThemeForm(templateName) {
const themeSelectorTemplate = document.querySelector(templateName)
const form = themeSelectorTemplate.content.firstElementChild
themeSelectorTemplate.replaceWith(form)

form.addEventListener('change', (e) => {
const chosenColorScheme = e.target.value
localStorage.setItem('theme', chosenColorScheme)
toggleTheme(chosenColorScheme)
})

const selectedTheme = localStorage.getItem('theme')
if (selectedTheme && selectedTheme !== 'undefined') {
form.querySelector(`[value="${selectedTheme}"]`).checked = true
}
}

const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
window.addEventListener('load', () => {
let hasDarkRules = false
for (const styleSheet of Array.from(document.styleSheets)) {
let mediaRules = []
for (const cssRule of styleSheet.cssRules) {
if (cssRule.type !== CSSRule.MEDIA_RULE) {
continue
}
// WARNING: Safari does not have/supports `conditionText`.
if (cssRule.conditionText) {
if (cssRule.conditionText !== prefersColorSchemeDark) {
continue
}
} else {
if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
continue
}
}
mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
}

// WARNING: do not try to insert a Rule to a styleSheet you are
// currently iterating on, otherwise the browser will be stuck
// in a infinite loop…
for (const mediaRule of mediaRules) {
styleSheet.insertRule(mediaRule.cssText)
hasDarkRules = true
}
}
if (hasDarkRules) {
loadThemeForm('#theme-selector')
}
})
</script>
</body>
</html>

+ 214
- 0
cache/2024/ad911ebf7ba5523ef0be1bdd599f7623/index.md View File

@@ -0,0 +1,214 @@
title: JavaScript Bloat in 2024
url: https://tonsky.me/blog/js-bloat/
hash_url: ad911ebf7ba5523ef0be1bdd599f7623
archive_date: 2024-03-03
og_image: https://dynogee.com/gen?id=dhqv5e0x3kfz7dy&title=JavaScript Bloat in 2024
description: What is the average size of JavaScript code downloaded per website? Fuck around and find out!
favicon: https://tonsky.me/i/favicon.png
language: en_US

<p><em>Translations: <a href="https://habr.com/ru/companies/ruvds/articles/796595/" target="_blank">Russian</a></em></p>
<p>I was a bit out of touch with modern front-end development. I also remembered articles about web bloat, how the average web page size was approaching several megabytes!</p>
<p>So all this time I was living under impression that, for example, if the average web page size is 3 MB, then JavaScript bundle should be around 1 MB. Surely content should still take the majority, no?</p>
<p>Well, the only way to find out is to fuck around. Let’s do a reality check!</p>
<p>I’m writing this in 2024, so maybe do a sequel in a few years?</p>
<h1 id="method">Method</h1>
<ul>
<li>Firefox on macOS (but should be the same in any browser)</li>
<li>Not incognito (I want to see numbers <em>inside</em> the app, and there’s a better chance it will resemble actual everyday experience)</li>
<li>All extensions disabled</li>
<li>JavaScript only</li>
<li>Uncompressed</li>
<li>Service Workers enabled (again, more real-life)</li>
<li>All caching disabled (cold load)</li>
</ul>
<p>Why only JavaScript? Content varies a lot from site to site (surely videos on YouTube are heavier than text messages on Slack), but JavaScript is a universal metric for “complexity of interactions”.</p>
<p>The main goal is to evaluate how much work the browser has to do to parse and execute code.</p>
<p>To set some baseline, let’s start with this blog:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/tonsky@2x.webp?t=1709315366"> </figure>
<p>The number here would be 0.004 MB. I also highlighted all the important bits you need to set if you decide to reproduce this at home.</p>
<h1 id="landings">Landings</h1>
<p>Okay, let’s start with something simple, like landing pages/non-interactive apps.</p>
<p>A normal slightly interactive page looks like this — Wikipedia, 0.2 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/wikipedia@2x.webp?t=1709315366"> </figure>
<p>Slightly bloated — like this — Linear, 3 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/linear@2x.webp?t=1709315366"> </figure>
<p>Remember: that’s without images, or videos, or even styles! Just JS code.</p>
<p>A bad landing page looks like this — Zoom, 6 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/zoom@2x.webp?t=1709315366"> </figure>
<p>or like Vercel, 6 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/vercel@2x.webp?t=1709315366"> </figure>
<p>Yes, this is just a landing page. No app, no functionality, no calls. 6 MB of JavaScript just for that.</p>
<p>You can do a lot worse, though — Gitlab, 13 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/gitlab@2x.webp?t=1709315366"> </figure>
<p>Still just the landing.</p>
<h1 id="mostly-static-websites">Mostly static websites</h1>
<p>Nothing simpler than showing a static wall of text. Medium needs 3 MB just to do that:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/medium@2x.webp?t=1709315366"> </figure>
<p>Substack needs 4 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/substack@2x.webp?t=1709315366"> </figure>
<p>Progress?</p>
<p>Quora, 4.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/quora@2x.webp?t=1709315366"> </figure>
<p>Pinterest, 10 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/pinterest@2x.webp?t=1709315366"> </figure>
<p>Patreon, 11 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/patreon@2x.webp?t=1709315366"> </figure>
<p>And all this could’ve been a static page...</p>
<h1 id="search">Search</h1>
<p>When your app’s interactivity is limited to mostly search. Type the query — show the list of results. How heavy is that?</p>
<p>StackOverflow, 3.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/stackoverflow@2x.webp?t=1709315366"> </figure>
<p>NPM, 4 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/npmjs@2x.webp?t=1709315366"> </figure>
<p>Airbnb, 7 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/airbnb@2x.webp?t=1709315366"> </figure>
<p>Booking.com, 12 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/booking@2x.webp?t=1709315366"> </figure>
<p>But Niki, booking is complicated! Look at all this UI! All these filters. All these popups about people near you stealing your vacation!</p>
<p>Okay, okay. Something simpler then. Google. How about Google? One text field, list of links. Right?</p>
<p>Well, it’ll cost you whooping 9 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/google@2x.webp?t=1709315366"> </figure>
<p>Just to show a list of links.</p>
<h1 id="simple-one-interaction-apps">Simple one-interaction apps</h1>
<p>Google Translate is just two text boxes. For that, you need 2.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/google_translate@2x.webp?t=1709315366"> </figure>
<p>ChatGPT is <em>one</em> text box. 7 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/openai@2x.webp?t=1709315366"> </figure>
<p>I mean, surely, ChatGPT is complex. But on the server, not in the browser!</p>
<h1 id="videos">Videos</h1>
<p>Loom — 7 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/loom@2x.webp?t=1709315366"> </figure>
<p>YouTube — 12 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/youtube@2x.webp?t=1709315366"> </figure>
<p>Compare it to people who really care about performance — Pornhub, 1.4 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/pornhub@2x.webp?t=1709315366"> </figure>
<h1 id="audio">Audio</h1>
<p>I guess audio just requires 12 MB no matter what:</p>
<p>SoundCloud:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/soundcloud@2x.webp?t=1709315366"> </figure>
<p>Spotify:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/spotify@2x.webp?t=1709315366"> </figure>
<h1 id="email">Email</h1>
<p>Okay, video and audio are probably heavy stuff (even though we are not measuring content, just JS, remember!). Let’s move to simpler office tasks.</p>
<p>Google Mail is just (just!) 20 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/gmail@2x.webp?t=1709315366"> </figure>
<p>It’s a freaking mailbox!!! How on earth is it almost as big as Figma, who ships entire custom C++/OpenGL rendering for their app?</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/figma@2x.webp?t=1709315366"> </figure>
<p>And if you are thinking: mail is complicated, too. Lots of UI, lots of interactivity. Maybe 20 MB is okay?</p>
<p>No!</p>
<p>Just no. See, FastMail, same deal, but only 2 MB. 10× less!</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/fastmail@2x.webp?t=1709315366"> </figure>
<h1 id="productivity">Productivity</h1>
<p>Okay, maybe e-mail is too complicated? How about something even simpler? Like a TODO list?</p>
<p>Well, meet Todoist, 9 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/todoist@2x.webp?t=1709315366"> </figure>
<p>Showing you a list of files in folders requires 10 MB in Dropbox:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/dropbox@2x.webp?t=1709315366"> </figure>
<p>List of passwords? That’ll be 13 MB on 1Password:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/1password@2x.webp?t=1709315366"> </figure>
<p>Cards? Add 0.5 MB more, up to 13.5 MB. Trello:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/trello@2x.webp?t=1709315366"> </figure>
<p>Okay, maybe TODO lists are too complex, too? How about chatting?</p>
<p>Well, Discord needs 21 MB to do that:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/discord@2x.webp?t=1709315366"> </figure>
<h1 id="document-editing">Document editing</h1>
<p>Okay, document editing is hard, right? You have to implement cursor movement, synchronization, etc.</p>
<p>Google Docs, 13.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/google_docs@2x.webp?t=1709315366"> </figure>
<p>Something simpler? Notion, 16 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/notion@2x.webp?t=1709315366"> </figure>
<h1 id="social-networks">Social Networks</h1>
<p>The typical size of code that social networks need for like buttons to go brrr is 12 MB.</p>
<p>Twitter, 11 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/twitter@2x.webp?t=1709315366"> </figure>
<p>Facebook, 12 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/facebook@2x.webp?t=1709315366"> </figure>
<p>TikTok, 12.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/tiktok@2x.webp?t=1709315366"> </figure>
<p>Instagram is somehow bigger than Facebook, despite having like 10× less functions. 16 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/instagram@2x.webp?t=1709315366"> </figure>
<p>LinkedIn. Is it a blog? A platform? It has search, it has messaging, it has social functions. Anyways, that’ll be 31 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/linkedin@2x.webp?t=1709315366"> </figure>
<p>By the way, I'd like to add you to my professional network on LinkedIn.</p>
<h1 id="elephants--its-own-category">Elephants — its own category</h1>
<p>Sometimes websites are so stupidly, absurdly large that they deserve their own category.</p>
<p>Here, Jira, a task management software. Almost 50 MB!</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/jira@2x.webp?t=1709315366"> </figure>
<p>Do they ship the entire Electron compiled WASM or what?</p>
<p>But that’s not the limit! Slack adds 5 more MB, up to 55 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/slack@2x.webp?t=1709315366"> </figure>
<p>Yes, it’s a chat. You know, list of users, messages, reactions. Stuff we did on raw HTML, even before JS was invented?</p>
<p>That’s 55 MB in today’s world. It’s almost like they are trying to see how much more bullshit can they put in a browser before it breaks.</p>
<p>Finally, this blew my mind. Somehow <a href="https://react.dev/blog/2023/03/16/introducing-react-dev" target="_blank">react.dev</a> starts with a modest 2 MB but as you scroll back and forth, it grows indefinitely. Just for fun, I got it to 100 MB (of JavaScript!), but you can go as far as you like:</p>
<figure>
<video autoplay="" muted="" loop="" preload="auto" playsinline="" controls="">
<source src="https://tonsky.me/blog/js-bloat/react@2x.mp4?t=1708621056" type="video/mp4">
</source></video>
</figure>
<p>What is going on there? Even if it unloads and downloads parts of that blog post, how is it growing so quickly? The text itself is probably only 50 KB (0.05 MB).</p>
<p>UPD: It has been brought to my attention that this behavior is not, in fact, representative of normal user experience. Normally embedded code editors will be cached after first load and subsequent loads will be served from disk cache. So as you scroll, you will see no network traffic, but these 100 MB of JS will still be parsed, evaluated and initialized over and over as you scroll.</p>
<h1 id="how-fast-are-we-degrading">How fast are we degrading?</h1>
<p>Look how cute! In 2015 average web page size was approaching shareware version of Doom 1 (2.5 MB):</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/bloat_2015@2x.webp?t=1709315366"><figcaption><a href="https://twitter.com/xbs/status/626781529054834688" target="_blank">Source</a></figcaption> </figure>
<p>Well, in 2024, Slack pulls up 55 MB, the size of the original Quake 1 with all the resources. But now it’s just in JavaScript alone.</p>
<p>For a chat app!</p>
<h1 id="how-big-is-10-mb-anyway">How big is 10 MB anyway?</h1>
<p>To be honest, after typing all these numbers, 10 MB doesn’t even feel that big or special. Seems like shipping 10 MB of <em>code</em> is normal now.</p>
<p>If we assume that the average code line is about 65 characters, that would mean we are shipping ~150,000 lines of code. With every website! Sometimes just to show static content!</p>
<p>And that code is minified already. So it’s more like 300K+ LoC just for one website.</p>
<p>But are modern websites really <em>that</em> complex? The poster child of SPAs, Google Maps, is quite modest by modern standards — is <em>still</em> just 4.5 MB:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/google_maps@2x.webp?t=1709315366"> </figure>
<p>Somebody at Google is seriously falling behind. Written with modern front-end technologies, it should be at least 20 MB.</p>
<p>And if you, like me, thought that “Figma is a really complex front-end app, so it must have a huge javascript download size”, well, that’s correct, but then Gmail is about as complex as Figma, LinkedIn is 1.5× more complex and Slack is 2.5× more ¯\_(ツ)_/¯</p>
<h1 id="conclusion">Conclusion</h1>
<p>It’s not just about download sizes. I welcome high-speed internet as much as the next guy. But code — JavaScript — is something that your browser has to parse, keep in memory, execute. It’s not free. And these people talk about performance and battery life...</p>
<p>Call me old-fashioned, but I firmly believe content should outweigh code size. If you are writing a blog post for 10K characters, you don’t need 1000× more JavaScript to render it.</p>
<p>This site is doing it right:</p>
<figure>
<img src="https://tonsky.me/blog/js-bloat/jquery@2x.webp?t=1709315366"> </figure>
<p>That’s 0.1 MB. And that’s enough!</p>
<p>And yet, on the same internet, in the same timeline, Gitlab needs 13 MB of code, 500K+ LoC of JS, just to display a static landing page.</p>
<p>Fuck me.</p>

+ 10
- 0
cache/2024/index.html View File

@@ -80,6 +80,8 @@
<li><a href="/david/cache/2024/959374400b4bb6d58c74116ffd08281b/" title="Accès à l’article dans le cache local : YOLO Ver">YOLO Ver</a> (<a href="https://yolover.org/" title="Accès à l’article original distant : YOLO Ver">original</a>)</li>
<li><a href="/david/cache/2024/24716a84007189a332fd8db3e5ff4c05/" title="Accès à l’article dans le cache local : rêve - Carnets Web de La Grange">rêve - Carnets Web de La Grange</a> (<a href="https://www.la-grange.net/2024/02/20/reve" title="Accès à l’article original distant : rêve - Carnets Web de La Grange">original</a>)</li>
<li><a href="/david/cache/2024/bf61b62532f71e39e7b92c76dc36bb0f/" title="Accès à l’article dans le cache local : Popover API (Explainer)">Popover API (Explainer)</a> (<a href="https://open-ui.org/components/popover.research.explainer/" title="Accès à l’article original distant : Popover API (Explainer)">original</a>)</li>
<li><a href="/david/cache/2024/d236f33cf82727313d17cb23bf36a395/" title="Accès à l’article dans le cache local : Reconsider your partnership with Brave">Reconsider your partnership with Brave</a> (<a href="https://kagifeedback.org/d/2808-reconsider-your-partnership-with-brave/6" title="Accès à l’article original distant : Reconsider your partnership with Brave">original</a>)</li>
@@ -188,6 +190,8 @@
<li><a href="/david/cache/2024/85b765a918ef094a5a2dd13a1ff5dd7d/" title="Accès à l’article dans le cache local : RSS 2.0 Specification">RSS 2.0 Specification</a> (<a href="https://www.rssboard.org/rss-specification#extendingRss" title="Accès à l’article original distant : RSS 2.0 Specification">original</a>)</li>
<li><a href="/david/cache/2024/ad911ebf7ba5523ef0be1bdd599f7623/" title="Accès à l’article dans le cache local : JavaScript Bloat in 2024">JavaScript Bloat in 2024</a> (<a href="https://tonsky.me/blog/js-bloat/" title="Accès à l’article original distant : JavaScript Bloat in 2024">original</a>)</li>
<li><a href="/david/cache/2024/87c468a4eddabe5d2c28e902d7f17504/" title="Accès à l’article dans le cache local : je ne sais pas pourquoi">je ne sais pas pourquoi</a> (<a href="https://www.la-grange.net/2024/01/11/pourquoi" title="Accès à l’article original distant : je ne sais pas pourquoi">original</a>)</li>
<li><a href="/david/cache/2024/3ea27fca4fabb81676fc1b98264f3bd8/" title="Accès à l’article dans le cache local : It’s OK to call it Artificial Intelligence">It’s OK to call it Artificial Intelligence</a> (<a href="https://simonwillison.net/2024/Jan/7/call-it-ai/" title="Accès à l’article original distant : It’s OK to call it Artificial Intelligence">original</a>)</li>
@@ -212,6 +216,8 @@
<li><a href="/david/cache/2024/81e8bd49021e320b84e5d4fbd4c7f587/" title="Accès à l’article dans le cache local : Se réapproprier nos conflits">Se réapproprier nos conflits</a> (<a href="https://cqfd-journal.org/Se-reapproprier-nos-conflits" title="Accès à l’article original distant : Se réapproprier nos conflits">original</a>)</li>
<li><a href="/david/cache/2024/4c8a04c4c0e928bd78f22db77425bb47/" title="Accès à l’article dans le cache local : No more forever projects">No more forever projects</a> (<a href="https://dianaberlin.com/posts/no-more-forever-projects" title="Accès à l’article original distant : No more forever projects">original</a>)</li>
<li><a href="/david/cache/2024/ea2cfc9aa425a6967d2cacd9f96ceb9e/" title="Accès à l’article dans le cache local : Ask LukeW: New Ways into Web Content">Ask LukeW: New Ways into Web Content</a> (<a href="https://lukew.com/ff/entry.asp?2008" title="Accès à l’article original distant : Ask LukeW: New Ways into Web Content">original</a>)</li>
<li><a href="/david/cache/2024/2cadf792810f64540605c86a1431cb6b/" title="Accès à l’article dans le cache local : Custom Forms with Web Components and "ElementInternals"">Custom Forms with Web Components and "ElementInternals"</a> (<a href="https://dev.to/stuffbreaker/custom-forms-with-web-components-and-elementinternals-4jaj" title="Accès à l’article original distant : Custom Forms with Web Components and "ElementInternals"">original</a>)</li>
@@ -252,6 +258,8 @@
<li><a href="/david/cache/2024/1929f7183f694c7abeafeddb891fcf50/" title="Accès à l’article dans le cache local : Crise des opioïdes : pourquoi il ne faut ni l'oublier ni l'ignorer">Crise des opioïdes : pourquoi il ne faut ni l'oublier ni l'ignorer</a> (<a href="https://basta.media/crise-des-opioides-pourquoi-il-ne-faut-ni-oublier-ni-ignorer" title="Accès à l’article original distant : Crise des opioïdes : pourquoi il ne faut ni l'oublier ni l'ignorer">original</a>)</li>
<li><a href="/david/cache/2024/a122504621c3c5318c0bdee38ef4479b/" title="Accès à l’article dans le cache local : Capo.js: A five minute web performance boost">Capo.js: A five minute web performance boost</a> (<a href="https://frontendmasters.com/blog/capo-js-a-five-minute-web-performance-boost/" title="Accès à l’article original distant : Capo.js: A five minute web performance boost">original</a>)</li>
<li><a href="/david/cache/2024/6bfc6bd7bc1d9158aa7f6591123e7f4b/" title="Accès à l’article dans le cache local : The Simplest Ways to Handle HTML Includes">The Simplest Ways to Handle HTML Includes</a> (<a href="https://css-tricks.com/the-simplest-ways-to-handle-html-includes/" title="Accès à l’article original distant : The Simplest Ways to Handle HTML Includes">original</a>)</li>
<li><a href="/david/cache/2024/71d5226ddc436248164884b12f15ed42/" title="Accès à l’article dans le cache local : Wikipédia ou la désillusion de l’intelligence collective">Wikipédia ou la désillusion de l’intelligence collective</a> (<a href="https://write.apreslanu.it/tk/wikipedia-ou-la-desillusion-de-lintelligence-collective" title="Accès à l’article original distant : Wikipédia ou la désillusion de l’intelligence collective">original</a>)</li>
@@ -292,6 +300,8 @@
<li><a href="/david/cache/2024/359df603dbf60e8476027b2eb26cb7ce/" title="Accès à l’article dans le cache local : uv: Python packaging in Rust">uv: Python packaging in Rust</a> (<a href="https://astral.sh/blog/uv" title="Accès à l’article original distant : uv: Python packaging in Rust">original</a>)</li>
<li><a href="/david/cache/2024/6fc45aab6c9584cbb6f55ef70a685d01/" title="Accès à l’article dans le cache local : Climat : pourquoi les températures battent tous les records depuis la mi-2023">Climat : pourquoi les températures battent tous les records depuis la mi-2023</a> (<a href="https://www.lemonde.fr/les-decodeurs/article/2024/03/03/climat-pourquoi-les-temperatures-battent-tous-les-records-depuis-la-mi-2023_6219806_4355770.html" title="Accès à l’article original distant : Climat : pourquoi les températures battent tous les records depuis la mi-2023">original</a>)</li>
<li><a href="/david/cache/2024/84f8caf3e7f7b3de9e18281749c3687f/" title="Accès à l’article dans le cache local : Until the Right Design Emerges...">Until the Right Design Emerges...</a> (<a href="https://lukew.com/ff/entry.asp?2036" title="Accès à l’article original distant : Until the Right Design Emerges...">original</a>)</li>
<li><a href="/david/cache/2024/cd2fda3dae5d89990f73fbdaa1c3b491/" title="Accès à l’article dans le cache local : build a world, not an audience">build a world, not an audience</a> (<a href="https://keningzhu.com/journal/build-a-world-not-an-audience" title="Accès à l’article original distant : build a world, not an audience">original</a>)</li>

Loading…
Cancel
Save