A place to cache linked articles (think custom and personal wayback machine)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.html 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. <!doctype html><!-- This is a valid HTML5 document. -->
  2. <!-- Screen readers, SEO, extensions and so on. -->
  3. <html lang="fr">
  4. <!-- Has to be within the first 1024 bytes, hence before the `title` element
  5. See: https://www.w3.org/TR/2012/CR-html5-20121217/document-metadata.html#charset -->
  6. <meta charset="utf-8">
  7. <!-- Why no `X-UA-Compatible` meta: https://stackoverflow.com/a/6771584 -->
  8. <!-- The viewport meta is quite crowded and we are responsible for that.
  9. See: https://codepen.io/tigt/post/meta-viewport-for-2015 -->
  10. <meta name="viewport" content="width=device-width,initial-scale=1">
  11. <!-- Required to make a valid HTML5 document. -->
  12. <title>Speed for who? | Andy Bell (archive) — David Larlet</title>
  13. <meta name="description" content="Publication mise en cache pour en conserver une trace.">
  14. <!-- That good ol' feed, subscribe :). -->
  15. <link rel="alternate" type="application/atom+xml" title="Feed" href="/david/log/">
  16. <!-- Generated from https://realfavicongenerator.net/ such a mess. -->
  17. <link rel="apple-touch-icon" sizes="180x180" href="/static/david/icons2/apple-touch-icon.png">
  18. <link rel="icon" type="image/png" sizes="32x32" href="/static/david/icons2/favicon-32x32.png">
  19. <link rel="icon" type="image/png" sizes="16x16" href="/static/david/icons2/favicon-16x16.png">
  20. <link rel="manifest" href="/static/david/icons2/site.webmanifest">
  21. <link rel="mask-icon" href="/static/david/icons2/safari-pinned-tab.svg" color="#07486c">
  22. <link rel="shortcut icon" href="/static/david/icons2/favicon.ico">
  23. <meta name="msapplication-TileColor" content="#f7f7f7">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f7f7f7" media="(prefers-color-scheme: light)">
  26. <meta name="theme-color" content="#272727" media="(prefers-color-scheme: dark)">
  27. <!-- Documented, feel free to shoot an email. -->
  28. <link rel="stylesheet" href="/static/david/css/style_2021-01-20.css">
  29. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  30. <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>
  31. <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>
  32. <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>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  36. <script>
  37. function toggleTheme(themeName) {
  38. document.documentElement.classList.toggle(
  39. 'forced-dark',
  40. themeName === 'dark'
  41. )
  42. document.documentElement.classList.toggle(
  43. 'forced-light',
  44. themeName === 'light'
  45. )
  46. }
  47. const selectedTheme = localStorage.getItem('theme')
  48. if (selectedTheme !== 'undefined') {
  49. toggleTheme(selectedTheme)
  50. }
  51. </script>
  52. <meta name="robots" content="noindex, nofollow">
  53. <meta content="origin-when-cross-origin" name="referrer">
  54. <!-- Canonical URL for SEO purposes -->
  55. <link rel="canonical" href="https://andy-bell.co.uk/speed-for-who/">
  56. <body class="remarkdown h1-underline h2-underline h3-underline em-underscore hr-center ul-star pre-tick" data-instant-intensity="viewport-all">
  57. <article>
  58. <header>
  59. <h1>Speed for who? | Andy Bell</h1>
  60. </header>
  61. <nav>
  62. <p class="center">
  63. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  64. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  65. </svg> Accueil</a> •
  66. <a href="https://andy-bell.co.uk/speed-for-who/" title="Lien vers le contenu original">Source originale</a>
  67. </p>
  68. </nav>
  69. <hr>
  70. <p><time datetime="2023-01-31">January 31, 2023 2:55 pm</time></p>
  71. <p>Frameworks are often touted as something like “a lightning fast development experience” and that’s fine I guess, but the speed is in the wrong hands. Why not “a lightning fast experience for your users”? </p>
  72. <p>Sure, some frameworks will claim to be very fast for end-users with some very meticulously, massaged data to “prove” that, but as Zach points out in <a href="https://www.zachleat.com/web/javascript-community/">this great post</a>, it means nothing when the output bundle sizes are astronomical off the bat: </p>
  73. <blockquote class="wp-block-quote">
  74. <p>Well, wait. When you’re straddling the divide, you know that <a href="https://www.zachleat.com/twitter/1534588439580090368/">Remix</a> (67.7 kB compressed) and <a href="https://www.zachleat.com/twitter/1584995586918731776/">Next.js</a> (90 kB compressed) have not meaningfully reduced their bundle sizes at all. Measurement reveals that bundles are growing: Next.js was <a href="https://www.zachleat.com/twitter/1468419834501337088">72.2 kB compressed in 2021</a>.</p>
  75. </blockquote>
  76. <p>I’ve always found the focus on developer experience as a framework feature uncomfortable. The focus is all in the wrong place: spoiled developers vs people trying to use your website/app. I personally think developer experience is one of the least important aspects.</p>
  77. <p>When I’ve mentioned that before, I often get a response like “yeh but because developer experience is better, we can do good work for users, faster”, but I’m yet to actually see that happening. Instead I see fad-chasing, like single page applications (SPAs), blockchain and now “AI” like Copilot and ChatGPT…</p>
  78. <p>If a framework actually came along with a pure focus on user experience and thoroughly optimised output—something like a 99% reduction in output JavaScript vs current frameworks—I would be interested. As Dave pointed out in this article, <a href="https://daverupert.com/2023/01/so-you-want-to-make-a-new-js-framework/">that goes against the new framework trend</a>.</p>
  79. <p>Only recently too, the head-honcho of Vercel—who are responsible for the monstrously large output generating framework—Next.js, tweeted this rather cryptic tweet: </p>
  80. <p>I personally think this is broetry that really translates to “remember how we consistently said that SPAs are much better and faster than real HTML pages? Guess what, we were actually grifting our framework and now we’re going to go against that original grift with a different grift for the same framework”. </p>
  81. <p>I dunno, maybe I’m being salty, but it’s justified saltiness. I actually <strong>genuinely care about users</strong>, you see. It’s why I <em>constantly</em> prattle on about progressive enhancement. Mainly, that makes everyone’s experience better, but the most important thing for me is that <strong>data is expensive.</strong> </p>
  82. <p>Sure, if you’re based in San Francisco and you go to your adult daycare—sorry, I mean startup office—with ultra high-speed broadband: that 90 kB baseline compressed output might not feel like a lot, but what about if you live in Saint Helena? At the time of writing, a gigabyte of data there <a href="https://www.cable.co.uk/mobiles/worldwide-data-pricing/#pricing">costs around $41 USD</a>. </p>
  83. <p>Your initial response to that might be “there’s a lot of kilobytes in a gigabyte”, and yes, you’re right, but there’s also a horrendous amount of framework-powered sites that could be HTML and CSS. Also, remember 90 kB is the framework’s default compressed output. Absolutely shoddy stuff. </p>
  84. <p>You might also be tempted to say “our users only live in ‘developed countries'” (god I hate that term), but that’s like saying “<a href="https://andy-bell.co.uk/most-of-our-users-are-on-desktop/" data-type="post" data-id="692">all of our users are on desktop</a>“. It’s also a piss-poor excuse for not building for everyone. </p>
  85. <p>I guess what I’m winding up to say here is developer experience really isn’t important—especially when frameworks haven’t even got the absolute baseline experience anywhere near where it needs to be to service a <strong>world wide web</strong>. A <strong>world wide web</strong> that’s accessed with slow, expensive connections and cheap, underperforming hardware. How about taking a bit of “DX” on the chin to focus instead on “why are we using this framework that potentially excludes the majority of users?”.</p>
  86. <p>As Alex says: <a href="https://infrequently.org/2022/12/performance-baseline-2023/">a lost decade</a>. I couldn’t agree with that sentiment more, to be honest.</p>
  87. </article>
  88. <hr>
  89. <footer>
  90. <p>
  91. <a href="/david/" title="Aller à l’accueil"><svg class="icon icon-home">
  92. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-home"></use>
  93. </svg> Accueil</a> •
  94. <a href="/david/log/" title="Accès au flux RSS"><svg class="icon icon-rss2">
  95. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-rss2"></use>
  96. </svg> Suivre</a> •
  97. <a href="http://larlet.com" title="Go to my English profile" data-instant><svg class="icon icon-user-tie">
  98. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-user-tie"></use>
  99. </svg> Pro</a> •
  100. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel"><svg class="icon icon-mail">
  101. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-mail"></use>
  102. </svg> Email</a> •
  103. <abbr class="nowrap" title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340"><svg class="icon icon-hammer2">
  104. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-hammer2"></use>
  105. </svg> Légal</abbr>
  106. </p>
  107. <template id="theme-selector">
  108. <form>
  109. <fieldset>
  110. <legend><svg class="icon icon-brightness-contrast">
  111. <use xlink:href="/static/david/icons2/symbol-defs-2021-12.svg#icon-brightness-contrast"></use>
  112. </svg> Thème</legend>
  113. <label>
  114. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  115. </label>
  116. <label>
  117. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  118. </label>
  119. <label>
  120. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  121. </label>
  122. </fieldset>
  123. </form>
  124. </template>
  125. </footer>
  126. <script src="/static/david/js/instantpage-5.1.0.min.js" type="module"></script>
  127. <script>
  128. function loadThemeForm(templateName) {
  129. const themeSelectorTemplate = document.querySelector(templateName)
  130. const form = themeSelectorTemplate.content.firstElementChild
  131. themeSelectorTemplate.replaceWith(form)
  132. form.addEventListener('change', (e) => {
  133. const chosenColorScheme = e.target.value
  134. localStorage.setItem('theme', chosenColorScheme)
  135. toggleTheme(chosenColorScheme)
  136. })
  137. const selectedTheme = localStorage.getItem('theme')
  138. if (selectedTheme && selectedTheme !== 'undefined') {
  139. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  140. }
  141. }
  142. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  143. window.addEventListener('load', () => {
  144. let hasDarkRules = false
  145. for (const styleSheet of Array.from(document.styleSheets)) {
  146. let mediaRules = []
  147. for (const cssRule of styleSheet.cssRules) {
  148. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  149. continue
  150. }
  151. // WARNING: Safari does not have/supports `conditionText`.
  152. if (cssRule.conditionText) {
  153. if (cssRule.conditionText !== prefersColorSchemeDark) {
  154. continue
  155. }
  156. } else {
  157. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  158. continue
  159. }
  160. }
  161. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  162. }
  163. // WARNING: do not try to insert a Rule to a styleSheet you are
  164. // currently iterating on, otherwise the browser will be stuck
  165. // in a infinite loop…
  166. for (const mediaRule of mediaRules) {
  167. styleSheet.insertRule(mediaRule.cssText)
  168. hasDarkRules = true
  169. }
  170. }
  171. if (hasDarkRules) {
  172. loadThemeForm('#theme-selector')
  173. }
  174. })
  175. </script>
  176. </body>
  177. </html>