A place to cache linked articles (think custom and personal wayback machine)
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

index.html 32KB

4 år sedan
4 år sedan
4 år sedan
4 år sedan
4 år sedan
4 år sedan
4 år sedan
4 år sedan
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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>
  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>Why 543 KB keep me up at night (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="#f0f0ea">
  24. <meta name="msapplication-config" content="/static/david/icons2/browserconfig.xml">
  25. <meta name="theme-color" content="#f0f0ea">
  26. <!-- Documented, feel free to shoot an email. -->
  27. <link rel="stylesheet" href="/static/david/css/style_2020-06-19.css">
  28. <!-- See https://www.zachleat.com/web/comprehensive-webfonts/ for the trade-off. -->
  29. <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>
  30. <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>
  31. <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>
  32. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_regular.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  33. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_bold.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  34. <link rel="preload" href="/static/david/css/fonts/triplicate_t3_italic.woff2" as="font" type="font/woff2" media="(prefers-color-scheme: dark)" crossorigin>
  35. <script type="text/javascript">
  36. function toggleTheme(themeName) {
  37. document.documentElement.classList.toggle(
  38. 'forced-dark',
  39. themeName === 'dark'
  40. )
  41. document.documentElement.classList.toggle(
  42. 'forced-light',
  43. themeName === 'light'
  44. )
  45. }
  46. const selectedTheme = localStorage.getItem('theme')
  47. if (selectedTheme !== 'undefined') {
  48. toggleTheme(selectedTheme)
  49. }
  50. </script>
  51. <meta name="robots" content="noindex, nofollow">
  52. <meta content="origin-when-cross-origin" name="referrer">
  53. <!-- Canonical URL for SEO purposes -->
  54. <link rel="canonical" href="https://www.matuzo.at/blog/why-543kb-keep-me-up-at-night/">
  55. <body class="remarkdown h1-underline h2-underline h3-underline hr-center ul-star pre-tick">
  56. <article>
  57. <header>
  58. <h1>Why 543 KB keep me up at night</h1>
  59. </header>
  60. <nav>
  61. <p class="center">
  62. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  63. <a href="https://www.matuzo.at/blog/why-543kb-keep-me-up-at-night/" title="Lien vers le contenu original">Source originale</a>
  64. </p>
  65. </nav>
  66. <hr>
  67. <main>
  68. <p>Some background: About three years ago I specialized in web accessibility. Now it’s not just my job to make sure that the websites I build are accessible, but the websites of others, too. I’m a front-end developer, but also a consultant and auditor. I’m employed for about a year now as well, and I have to evaluate a lot more third party web products than I used to.</p>
  69. <h2 id="something-has-changed">Something has changed</h2>
  70. <p>A friend recently sent me the link to a website and asked me for feedback, because I had experience with the content management system their client was using.<br/>I <a href="/blog/beyond-automatic-accessibility-testing-6-things-i-check-on-every-website-i-build/">checked a few things</a> and then browsed through the website with <a href="https://developer.mozilla.org/en-US/docs/Tools">Dev Tools</a> and the network panel open. The homepage had a page weight of <strong>4.1 MB (6.7 MB uncompressed)</strong>. I thought, “<em>Aight, that’s not great, but there are a bunch of images, so I guess it’s okay</em>”. Then I visited a page with a header, footer, sidebar navigation and a short paragraph <strong>(543 KB / 1.6 MB uncompressed)</strong> and I thought “<em>Nice, noticeably below 1 MB, that’s pretty good.</em>”.</p>
  71. <p>And then it hit me.<br/>What the hell did just happen? <strong>543 KB</strong> on a simple text-only page is OK? Fuck no, it’s not.</p>
  72. <p>How and when did I get to the point where I would consider a page weight of 4 MB on a large page and 500 KB on a small page normal? This got me thinking (and writing obviously). This is not an exception. The quality of most websites I audit and evaluate is bad. Somehow we've collectively decided that it’s okay to publish garbage.<br/>When I say we, I don’t just mean us developers. The reason could be a developer who doesn’t care enough, but it could also be a team lead, product owner or client who simply doesn’t give devs enough time to care about quality. Causes for that could be a lack of awareness, tough deadlines, short release cycles, or focus on development of new features instead of improvement of existing code.<br/>When I say garbage, I mean slow, inaccessible, annoying, stressful, or intrusive web experiences.</p>
  73. <h3 id="slow">Slow</h3>
  74. <p>I need 1.6 MB of JavaScript (7.2 MB uncompressed) to display a table with my billing history.</p>
  75. <figure class="figure figure--full"><a href="https://res.cloudinary.com/dp3mem7or/image/upload/v1582717566/articles/543kb/adobe_j.jpg" rel="noopener"><span class="content__image-wrapper"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazy content__image" data-src="https://res.cloudinary.com/dp3mem7or/image/upload/c_scale,w_1300/v1582717566/articles/543kb/adobe_j.jpg" alt="Logged in on adobe.com. Screenshot."/></span></a><figcaption>Billing history on adobe.com</figcaption></figure>
  76. <h3 id="inaccessible">Inaccessible</h3>
  77. <p>Many accessibility issues derive from bad markup. I could show a screenshot of any website here, but you’ll find some common mistakes on <a href="https://www.htmhell.dev/">HTMHell</a>.</p>
  78. <figure class="figure figure--full"><a href="https://www.htmhell.dev/10-section-is-no-replacement-for-div/" rel="noopener"><span class="content__image-wrapper"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazy content__image" data-src="https://res.cloudinary.com/dp3mem7or/image/upload/c_scale,w_1300/v1582719885/articles/543kb/htmhell.jpg" alt="htmhell.com. Screenshot."/></span></a><figcaption>A submission on HTMHell showing many nested section and article elements.</figcaption></figure>
  79. <h3 id="annoying">Annoying</h3>
  80. <p>No, the first thing I want to do when I visit your website is not to sign up for a newsletter.</p>
  81. <figure class="figure figure--full"><a href="https://res.cloudinary.com/dp3mem7or/image/upload/v1582780558/articles/543kb/sitepoint.jpg" rel="noopener"><span class="content__image-wrapper"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazy content__image" data-src="https://res.cloudinary.com/dp3mem7or/image/upload/c_scale,w_1300/v1582780558/articles/543kb/sitepoint.jpg" alt="Overlay on the sitepoint.com hopmepage. Screenshot."/></span></a><figcaption>Sitepoint trying to lure users into signing up for their newsletter by giving away a free book.</figcaption></figure>
  82. <h3 id="stressful">Stressful</h3>
  83. <p>Only 5 rooms left! Limited-time deal!! 2 other people looked for your dates in the last 10 minutes!!! I will never ever book anything on your website!!!!</p>
  84. <figure class="figure"><a href="https://res.cloudinary.com/dp3mem7or/image/upload/v1582780558/articles/543kb/booking.jpg" rel="noopener"><span class="content__image-wrapper"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazy content__image" data-src="https://res.cloudinary.com/dp3mem7or/image/upload/c_scale,w_800/v1582780558/articles/543kb/booking.jpg" alt="Room selection screen on booking.com. Red and orange messages stressing people to book quickly."/></span></a><figcaption>booking.com trying to stress me in 3 different places into booking a room.</figcaption></figure>
  85. <h3 id="intrusive">Intrusive</h3>
  86. <p>ZDNet misuses the cookie consent dialog to trigger the push notifications prompt.</p>
  87. <figure class="figure"><a href="https://res.cloudinary.com/dp3mem7or/image/upload/v1582780558/articles/543kb/zdnet.jpg" rel="noopener"><span class="content__image-wrapper"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazy content__image" data-src="https://res.cloudinary.com/dp3mem7or/image/upload/c_scale,w_1300/v1582780558/articles/543kb/zdnet.jpg" alt="Cookie dialog shows, click Allow, notifications prompt shows. "/></span></a><figcaption>A tweet by Šime Vidas explaining what he discovered on ZDNet.</figcaption></figure>
  88. <p>I don’t know if it has always been like that or if the quality of what we publish online has gotten worse with <a href="https://css-tricks.com/innovation-cant-keep-the-web-fast/">advancing technological possibilities on the web</a> (faster networks, more powerful tools and new APIs). <strong>The web is in bad shape - we need to readjust our understanding of what quality means</strong> and what we can expect our users to put up with.</p>
  89. <p>Now you might think, “<em>Dude, chill. 543 KB? That’s not bad, even on a 3G connection that site should load in a reasonable time.</em>”.</p>
  90. <h2 id="why-543-kb-might-be-bad">Why 543 KB might be bad</h2>
  91. <p>Yes, I know, it depends. 543 KB aren't always bad, but on that specific page there's only a single image (the logo ~20 KB) and a single paragraph. So why then is the page still relatively large, where are the remaining 523 KB coming from?</p>
  92. <p>Let's break it up and see what we could take into account when we evaluate the total transferred bytes.</p>
  93. <h3 id="page-weight">Page weight</h3>
  94. <p>Even in times of 4G or 5G, optimizing for fast download is important. People don’t always surf the web under the best conditions. Build your website for someone who visits it at Starbucks using Starbucks WIFI and not for someone who’s connected to their own fast internet at home.</p>
  95. <p>The website we’re talking about now is an Austrian website, in German language, accessed mostly by Austrians via Austrian networks. We’re a country with affordable and fast data. Don’t get me wrong, the page weight is definitely too big, but I’d argue that it's not the biggest issue, especially if they’re caching efficiently and prioritizing asset loading correctly (spoiler alert: they’re not… ).</p>
  96. <h3 id="dom-size">DOM size</h3>
  97. <p>Many and deeply nested elements result in a large DOM tree, which can affect runtime, memory and load performance negatively.</p>
  98. <p>A large DOM tree in combination with complicated styles might have a bad effect on page rendering. In his talk <em>“</em><a href="https://www.technica11y.org/performance-and-the-accessibility-tree"><em>The Intersection of Performance and Accessibility</em></a><em>”</em> <a href="https://ericwbailey.design/">Eric W. Bailey</a> gives an example of a form based on Material Design that caused the screen reader Voice Over to crash because of its massive DOM size.</p>
  99. <blockquote><p>To make a material design radio input, you need six HTML elements containing nine attributes with a DOM depth of three. You also need 66 CSS selectors containing 141 properties which weighs in at 10k when minified. You also need 2374 lines of JavaScript which weighs in at 30k when minified. All of this will get you a radio input.</p></blockquote>
  100. <p>Another factor is JavaScript. Updating complex DOM structures can get expensive, changes at one level in the DOM tree can cause changes at every level of the tree, which leads to more time being spent <a href="https://gist.github.com/paulirish/5d52fb081b3570c81e3a">performing reflow</a>. DOM operations can become a performance bottleneck, but there’s more to consider, like storing references to a large number of nodes, which might overwhelm the memory capabilities of devices. Creating DOM nodes only when needed and destroying them when no longer needed helps with that.</p>
  101. <p>If you don’t write your markup carefully and enable compression on the server, your HTML document might end up having multiple hundred kilobytes, although it should be somewhere in the lower tens. By writing carefully I mean only creating DOM nodes you need and adding extra divs and spans only when necessary. In React, <a href="https://reactjs.org/docs/fragments.html">Fragments</a> might help with that.</p>
  102. <pre class="language-js"><code class="language-js"><span class="highlight-line"><span class="token keyword">class</span> <span class="token class-name">Columns</span> <span class="token keyword">extends</span> <span class="token class-name">React<span class="token punctuation">.</span>Component</span> <span class="token punctuation">{</span></span><br/><span class="highlight-line"> <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></span><br/><span class="highlight-line"> <span class="token keyword">return</span> <span class="token punctuation">(</span></span><br/><span class="highlight-line"> <span class="token operator">&lt;</span>React<span class="token punctuation">.</span>Fragment<span class="token operator">&gt;</span></span><br/><span class="highlight-line"> <span class="token operator">&lt;</span>td<span class="token operator">&gt;</span>Hello<span class="token operator">&lt;</span><span class="token operator">/</span>td<span class="token operator">&gt;</span></span><br/><span class="highlight-line"> <span class="token operator">&lt;</span>td<span class="token operator">&gt;</span>World<span class="token operator">&lt;</span><span class="token operator">/</span>td<span class="token operator">&gt;</span></span><br/><span class="highlight-line"> <span class="token operator">&lt;</span><span class="token operator">/</span>React<span class="token punctuation">.</span>Fragment<span class="token operator">&gt;</span></span><br/><span class="highlight-line"> <span class="token punctuation">)</span><span class="token punctuation">;</span></span><br/><span class="highlight-line"> <span class="token punctuation">}</span></span><br/><span class="highlight-line"><span class="token punctuation">}</span></span></code></pre>
  103. <p>A fragment just returns the content within the fragment without an extra wrapper <code>div</code>.</p>
  104. <p><a href="https://developers.google.com/web/tools/lighthouse/audits/dom-size">Google recommends</a> less than 1500 nodes total, a maximum depth of 32 nodes, and no parent node with more than 60 child nodes.</p>
  105. <h3 id="css">CSS</h3>
  106. <p>There are 11 style sheets with a total weight of 97 KB (566 KB uncompressed). Only by looking at the numbers it’s hard to tell if there are a lot of unused rules in there, but 566 KB of minified CSS is definitely not something that can be ignored. I'm not saying that refactoring their CSS is a must, but I’d at least consider taking another look at what goes into the CSS bundle. Sometimes it’s not even our fault that bundle sizes are too big. Many content management systems or plug-ins come with huge JS and CSS files where only a fraction of the code is needed.</p>
  107. <p>Another thing worth considering is splitting up the main CSS file by media feature, especially if the assets are served via HTTP2.</p>
  108. <pre class="language-html"><code class="language-html"><span class="highlight-line"/><br/><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>main.css<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span></span><br/><span class="highlight-line"/><br/><span class="highlight-line"/><br/><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>medium.css<span class="token punctuation">"</span></span> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>(min-width: 768px)<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span></span><br/><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>large.css<span class="token punctuation">"</span></span> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>(min-width: 1024px)<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span></span><br/><span class="highlight-line"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>stylesheet<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>print.css<span class="token punctuation">"</span></span> <span class="token attr-name">media</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>print<span class="token punctuation">"</span></span> <span class="token punctuation">/&gt;</span></span></span></code></pre>
  109. <p>Before HTTP2 this was kinda considered a bad practice, but with HTTP2 multiplexing, the number of requests that can be sent to the server at the same time is no longer limited. The big advantage of splitting CSS into multiple files is that browsers will download all of them, but only those needed to fulfill the current context will block rendering,</p>
  110. <p>Read more about the topic in Harry Roberts fantastic article <a href="https://csswizardry.com/2018/11/css-and-network-performance/">CSS and Network Performance</a>.</p>
  111. <h3 id="fonts">Fonts</h3>
  112. <p>Font files can get pretty big, a <a href="https://www.zachleat.com/web/comprehensive-webfonts/">good font loading strategy</a> is essential. Fonts are sometimes a necessary evil, but one file is a 34 KB Font Awesome file. SVGs might be a better choice, because they're more flexible than icon fonts for animation and styling, and a SVG sprite with just the icons needed and not the whole set of icons might end up being much smaller.</p>
  113. <p>It’s been years since I’ve used services like Font Awesome, SVGs have so much <a href="https://css-tricks.com/icon-fonts-vs-svg/">more advantages over icons fonts</a>.</p>
  114. <h3 id="javascript-and-bundle-sizes">JavaScript and bundle sizes</h3>
  115. <p>There are 22 JS files with a total file size of 320 KB (886 KB compressed). This is way too much considering that there’s only a navigation and a share button on this page.</p>
  116. <p>I will not bash JavaScript, I love JS and I enjoy writing it. I’m not great at it though, and I’d argue that most of us aren’t. Lack of knowledge paired with a language that can easily fuck up performance is dangerous. That’s why I’m very cautious of what I’m doing and which 3rd party plugins I’m using.</p>
  117. <figure class="figure figure--full"><a href="https://res.cloudinary.com/dp3mem7or/image/upload/v1582780558/articles/543kb/addy.jpg" rel="noopener"><span class="content__image-wrapper"><img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" class="lazy content__image" data-src="https://res.cloudinary.com/dp3mem7or/image/upload/c_scale,w_1300/v1582780558/articles/543kb/addy.jpg" alt="Addy Osmani on the left on stage at #PerfMatters conf. A slide on the right “Stop taking fast networks, CPU &amp; high RAM for granted”."/></span></a></figure>
  118. <p>I’ve watched Addy Osmani’s <a href="https://www.youtube.com/watch?v=X9eRLElSW1c&amp;feature=emb_title">The Cost of JavaScript</a> the other day, which is also one reason I’m writing this article. I was blown away by so many things he said. Here’s a summary of my highlights:</p>
  119. <ul><li>JavaScript is one of the most expensive parts of your site, reduce how much JS you ship.</li><li>Small JavaScript bundles improve download speeds, lower memory usage, and reduce CPU costs.</li><li>Avoid large bundles <strong>(50KB+)</strong>.</li><li>Post-Download, executing JavaScript is the dominant cost.</li><li>The differences between a low-end phone and high-end phone are huge.</li><li>Fast JavaScript means fast at download, parse and compile, and execute.</li><li>Avoid large inline scripts.</li><li>If possible, split your JS code.</li><li>Audit JS regularly.</li><li>Make performance part of the conversation.</li><li>Stop taking fast networks, fast CPU, and high RAM for granted.</li><li>Test on real phones and networks.</li></ul>
  120. <p>Watch the talk or <a href="https://v8.dev/blog/cost-of-javascript-2019">read the article</a>, I promise you’ll love it.</p>
  121. <p>If you know more about performance than I do (and you probably do), you might be shouting at the screen <em>“You didn’t consider this and that”</em>. Fair enough, but this post is not about how to optimize those 543 KB. It was my attempt to show you that we can’t expect whatever we produce and put online to be fine. We have to be much more considerate, we have to take a second and third look, and constantly challenge our decisions. Sometimes, even just slowing down can make a difference. As <a href="https://hankchizljaw.com/wrote/keeping-it-simple-with-css-that-scales/">Andy Bell recently discovered</a> while reviewing a larger codebase, stepping back and ignoring time pressure for a moment can help with seeing things clearly.</p>
  122. <blockquote><p>We had two or three grid systems, some fluid type and some utility driven type that conflicted <strong>and</strong> a card component that was pretty much a website in itself. If I had slowed down and stepped back, I could have seen these problems, but I didn’t. So seriously, slow down and you will save so much time.</p></blockquote>
  123. <p><a href="https://hankchizljaw.com/" rel="noopener">Andy Bell</a></p>
  124. <p>By the way, the 543 KB page scored 11 points on the Lighthouse performance test.</p>
  125. <h2 id="why-bother">Why bother?</h2>
  126. <p>Why is a website I'll probably never visit again bothering me so much?<br/>Because someone decided that it was good enough to go live. The problem is not this specific website or how fast it loads, but that <strong>shipping seems to be so much more important than performance, usability, accessibility, or user experience</strong>. Again, I know it’s not always up to us, because often we just have to publish something we don’t agree with, but the least we can do is to educate others why some decisions might be harmful, and try to improve things in whatever ways we can.</p>
  127. <blockquote><p>It’s becoming increasingly clear that web performance isn’t solely an engineering problem, but a problem of people.</p></blockquote>
  128. <p><a href="https://css-tricks.com/innovation-cant-keep-the-web-fast/">Jeremy Wagner</a></p>
  129. <h2 id="whats-good-enough">Whats good enough?</h2>
  130. <p>I started this article with the question “how good is <em>good enough</em>”. I can’t answer it for all of us, because it depends on our personal experience and capabilities. What I consider good enough might not live up to the expectations of others, but there are standards and best practices we can follow.</p>
  131. <p>Here are a few things I (as a front-end dev) believe have to happen before a website can go online.</p>
  132. <ul><li><a href="https://validator.w3.org/">Validate your HTML.</a></li><li>Test in many browsers. There’s a world beyond Firefox and Chrome. Check Opera, Firefox Mobile, Brave, Edge, or Samsung Internet, just to name a few. Safari can be a bitch, too.</li><li>Test on low budget phones, if you really want to see how well your website performs.</li><li><a href="https://developers.google.com/web/tools/lighthouse">Run Lighthouse</a> and try to score 100 in the accessibility, best practices, and SEO audits. Scoring 100 in performance is hard, but strive for a score above 90.</li><li>Check how your site performs on a slow connection by <a href="https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor/Throttling">throttling it in Dev Tools</a>.</li><li>Put <a href="https://www.youtube.com/watch?v=H4FzW9oFObs">your mouse aside</a> and use your website with the keyboard only.</li><li><a href="https://dequeuniversity.com/screenreaders/">Test your site with screen readers</a>.</li><li>Go through <a href="https://thedaviddias.dev/">David Dias</a>' fantastic <a href="https://frontendchecklist.io/">Frontend Checklist</a>.</li></ul>
  133. <p>There’s more, but if we all did at least that, our users would be much happier. I know you might be thinking: <em>“We don’t have the budget for that.”</em>. But that’s the point: you should have it. <em>“It’s online and works in most browsers”</em> is not enough. We have to make performance, accessibility, usability, and user experience part of the conversation.</p>
  134. <p>By the time you’ve reached this paragraph, you’ve downloaded 837 KB of data. Can that be improved? Most definitely. Is this website 100% accessible? Probably not. Did you get the best possible user experience? I guess no, I don’t know shit about UX.<br/>If my own website isn’t perfect, who am I to lecture you? Well it’s not about publishing perfect websites. That’s not possible for many different reasons, but it’s important that we’re conscious of what we’re shipping to our users. It’s important that we care about our users and about the quality of our products and that our standards become higher than they are at the moment.</p>
  135. <blockquote><p>Good websites need time.<br/>Great websites need a lot of time.</p><p>For content, for graphics, for interaction, for organization, for findability, usability, accessibility and that dash of delight that makes it special.</p><p>Don’t build throw-away websites, build websites that last.</p></blockquote>
  136. <p><a href="https://mobile.twitter.com/yatil/status/1230899701802770442">Eric Eggert</a></p>
  137. <h2>Resources</h2>
  138. <ul><li><a href="https://www.technica11y.org/performance-and-the-accessibility-tree">Performance and the Accessibility Tree</a></li><li><a href="https://developers.google.com/web/tools/lighthouse/audits/dom-size">Uses An Excessive DOM Size</a></li><li><a href="https://areknawo.com/dom-performance-case-study/">DOM performance case study</a></li><li><a href="https://developers.google.com/web/fundamentals/performance/rendering/">Rendering Performance</a></li><li><a href="https://css-tricks.com/innovation-cant-keep-the-web-fast/">Innovation Can’t Keep the Web Fast</a></li><li><a href="https://www.filamentgroup.com/lab/5g/">5G Will Definitely Make the Web Slower, Maybe</a></li><li><a href="https://hankchizljaw.com/wrote/keeping-it-simple-with-css-that-scales/">Keeping it simple with CSS that scales</a></li></ul>
  139. </main>
  140. </article>
  141. <hr>
  142. <footer>
  143. <p>
  144. <a href="/david/" title="Aller à l’accueil">🏠</a> •
  145. <a href="/david/log/" title="Accès au flux RSS">🤖</a> •
  146. <a href="http://larlet.com" title="Go to my English profile" data-instant>🇨🇦</a> •
  147. <a href="mailto:david%40larlet.fr" title="Envoyer un courriel">📮</a> •
  148. <abbr title="Hébergeur : Alwaysdata, 62 rue Tiquetonne 75002 Paris, +33184162340">🧚</abbr>
  149. </p>
  150. <template id="theme-selector">
  151. <form>
  152. <fieldset>
  153. <legend>Thème</legend>
  154. <label>
  155. <input type="radio" value="auto" name="chosen-color-scheme" checked> Auto
  156. </label>
  157. <label>
  158. <input type="radio" value="dark" name="chosen-color-scheme"> Foncé
  159. </label>
  160. <label>
  161. <input type="radio" value="light" name="chosen-color-scheme"> Clair
  162. </label>
  163. </fieldset>
  164. </form>
  165. </template>
  166. </footer>
  167. <script type="text/javascript">
  168. function loadThemeForm(templateName) {
  169. const themeSelectorTemplate = document.querySelector(templateName)
  170. const form = themeSelectorTemplate.content.firstElementChild
  171. themeSelectorTemplate.replaceWith(form)
  172. form.addEventListener('change', (e) => {
  173. const chosenColorScheme = e.target.value
  174. localStorage.setItem('theme', chosenColorScheme)
  175. toggleTheme(chosenColorScheme)
  176. })
  177. const selectedTheme = localStorage.getItem('theme')
  178. if (selectedTheme && selectedTheme !== 'undefined') {
  179. form.querySelector(`[value="${selectedTheme}"]`).checked = true
  180. }
  181. }
  182. const prefersColorSchemeDark = '(prefers-color-scheme: dark)'
  183. window.addEventListener('load', () => {
  184. let hasDarkRules = false
  185. for (const styleSheet of Array.from(document.styleSheets)) {
  186. let mediaRules = []
  187. for (const cssRule of styleSheet.cssRules) {
  188. if (cssRule.type !== CSSRule.MEDIA_RULE) {
  189. continue
  190. }
  191. // WARNING: Safari does not have/supports `conditionText`.
  192. if (cssRule.conditionText) {
  193. if (cssRule.conditionText !== prefersColorSchemeDark) {
  194. continue
  195. }
  196. } else {
  197. if (cssRule.cssText.startsWith(prefersColorSchemeDark)) {
  198. continue
  199. }
  200. }
  201. mediaRules = mediaRules.concat(Array.from(cssRule.cssRules))
  202. }
  203. // WARNING: do not try to insert a Rule to a styleSheet you are
  204. // currently iterating on, otherwise the browser will be stuck
  205. // in a infinite loop…
  206. for (const mediaRule of mediaRules) {
  207. styleSheet.insertRule(mediaRule.cssText)
  208. hasDarkRules = true
  209. }
  210. }
  211. if (hasDarkRules) {
  212. loadThemeForm('#theme-selector')
  213. }
  214. })
  215. </script>
  216. </body>
  217. </html>