123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188 |
- <!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>The Content Management System of my Dreams (part 2) - The trouble with dynamic publishing (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)">
- <!-- 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.padawan.info/en/2023/02/the-content-management-system-of-my-dreams-part-2-the-trouble-with-dynamic-publishing.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>The Content Management System of my Dreams (part 2) - The trouble with dynamic publishing</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.padawan.info/en/2023/02/the-content-management-system-of-my-dreams-part-2-the-trouble-with-dynamic-publishing.html" title="Lien vers le contenu original">Source originale</a>
- </p>
- </nav>
- <hr>
- <h3>The trouble with dynamic publishing</h3>
- <p>PHP, Personal Home Page, popularized dynamic publishing. It gave way to blog engines, such as b2, b2evolution, <a href="https://dotclear.org">Dotclear</a>. Speaking of history, Movable Type was <em>the</em> number one blog engine loved by geeks and non geeks alike, and the few developers that would not burst in flames in front of Perl like sun-bathing vampires. When Six Apart made a brusque U-turn in killing the Open Source version of MT to pursue questionnable commercial ventures (because it was already well known that it is easier to make money out of other people's content rather than selling a CMS), a certain Matt Mullenweg saw the uproar of the community, took an opportunity by forking <a href="https://en.wikipedia.org/wiki/B2evolution">b2/cafelog</a> and rebranded it as WordPress. The crowd of bloggers took the bait and followed in droves. In one fell swoop Movable Type faded in history and WordPress took over the world.</p>
- <p>Web developers got so enamored with instantaneous “dynamic publishing” that the thought of having to click one more button and wait more than a few seconds to see a code change became unbearable. It would waste their time and by some twisted reasoning they decided that static publishing was old school and dynamic publishing was <em>soooo</em> in.<br>If it's good for them, it must be good for everyone else, right?</p>
- <p>This is why most “dynamic sites” will make a hundred calls to a database just to display <em>one</em> page to <em>one</em> visitor, even if its content never changes. Think about it this way: for each page view you are assembling the whole following scene along with summoning actors, the sea and some clouds for style, instead of just showing a print:</p>
- <p><img srcset="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/Theodore_Gericault_Raft_of_the_Medusa-1.jpg/640px-Theodore_Gericault_Raft_of_the_Medusa-1.jpg 640w" sizes="640px" src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c2/Theodore_Gericault_Raft_of_the_Medusa-1.jpg/266px-Theodore_Gericault_Raft_of_the_Medusa-1.jpg" alt="File:Theodore Gericault Raft of the Medusa-1.jpg" class="sdms-quick-view__thumbnail sdms-quick-view__thumbnail--loaded"></p>
- <p><em>“Ah! But you are doing it wrong! Just put a cache in front of it. Problem solved!”</em></p>
- <p>And there you have <em>two</em> problems. If you need an external cache in front of your CMS, <em>you</em> are doing it wrong.<br>Cache is one of the most difficult problems in IT. Its invalidation certainly is. If the cache is added in front of the CMS, rather than being managed by the CMS itself (like MT does), you now have two different systems that need more development and maintenance work to handle changes. Your site just became more costly and more difficult to manage.</p>
- <p>I have a concrete example of this point. A site is generating its home page dynamically. Because of performance issues (it can take more than 10 seconds to generate the page) an external cache has been added in front of the site. Now the site has a cache invalidation issue that prevents a small promotion block to update when a new item is added in the CMS. The adopted solution consists of throwing an ugly truck of javascript at the visitor's browser and have it make a call to an API to fetch the last two promotions. Yes, this is a “dynamic” site that requires a double request and three computations from two servers and the browser, for each view (at least for the latter when the web server cache works, I won't even talk about caching the API server response). I reckon that this site is wasting at least 10 times the energy and money that is reasonable. And of course absolutely nothing can be done on it, beyond content edition, without a highly specialized developer and a complex deployment process.</p>
- <p>Another obvious auto-inflicted problem are performance issues, which are almost always offset by throwing more horsepower in front of the slow carriage. On the Internet, nobody knows we are entertaining a whole menagerie to serve you this page.</p>
- <p>At a time where we all must seriously think about our ecological impact and energy use, it is not ok to not take a step back and question every architectural decision that needlessly multiply servers and computing cycles when we should know, and do, better. Lazyness is half-jokingly said to be good in development. This is not funny when it turns into self-centered decisions like switching to a dynamic system because a developer or a content editor does not care to wait while rebuilding a page. <strong>A few seconds saved for one person turn into a fantastic waste of time, money and energy for everyone else</strong>.</p>
- <p>I am serious about these aspects. There are concerning reports, most of them totally out of whack, pointing fingers at the Internet sector for its ecological waste. Let alone suicidal (literally), it would be absolutely hypocritical to dismiss them by cherry-picking where those reports are wrong (that's easy) while we are conveniently forgetting about the ecological impact of some of our decisions. We are responsible, and at some point in the near future, <strong><em>we will be held responsible for our footprint in the climate disaster</em></strong>.</p>
- <p>“But I <em>need</em> a dynamic site!”</p>
- <p>Do you, really?</p>
- <p>Think very hard about that word. What exactly is <em>dynamic</em> on your home page? Are you speaking about that Top News thingy? How often do they change? Are you doing this to satisfy yourself (some content editors have the same proclivity than developers to throw a tantrum because their new content does not appear instantaneously on the site)? Is this a business requirement or a real need of your users?</p>
- <p>Of course you might need dynamic pages, for example on backoffice sites, profile pages, pages that are unique to one user. But an outstanding majority of pages floating in the cloud do not need to be recalculated for each view. Even if they contain information that changes sometimes, especially if those information are not unique to any visitor.<br>And if you do need some dynamic pages, nothing prevents you to publish the rest as static files, especially for the most visited pages of your site.</p>
- <p>Here is an easy check point: <strong>if your pages show the same content to all visitors then <em>you do not need a dynamic site</em></strong>, regardless of the frequency of its changes.</p>
- <p>There is an ironic turn at this point in history. Stay tuned…</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>
|