123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- <!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>Comfort of Bloated Web (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://susam.net/maze/wall/comfort-of-bloated-web.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>Comfort of Bloated Web</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://susam.net/maze/wall/comfort-of-bloated-web.html" title="Lien vers le contenu original">Source originale</a>
- </p>
- </nav>
- <hr>
- <p>
- There is a tiny
- <a href="https://susam.net/form/comment/?post=hello">comment form</a>
- application on this website to accept comments from visitors and
- save them on the file system of the web server for me to review
- later and publish. This form is one of the only two things on this
- website that is dynamic in nature. The other dynamic part is
- the <a href="https://susam.net/form/subscribe/">subscription form</a>.
- Everything on this website other than these two things are static in
- nature.
- </p>
- <h2 id="mysterious-copies">Mysterious Copies<a href="#mysterious-copies"></a></h2>
- <p>
- Most of this website is made of handcrafted HTML. The blog posts and
- other content files are handcrafted HTML pages. A Common Lisp
- program adds common headers and footers to these pages and generates
- the HTML pages that are served as static files via Nginx running on
- a Debian system. The comment form, however, is a dynamic web
- application served via another Common Lisp program that makes use of
- the Hunchentoot web server to serve the form, accept the input
- submitted by the user, and then process it. This comment form is a
- very simple, minimal, and stateless application that fulfills the
- modest requirements of this modest website pretty well.
- </p>
- <p>
- However, often I see multiple copies of the same comment being saved
- on my web server. In the initial days of encountering this issue, I
- felt quite confused. I could rule out a bug in my program by
- carefully reviewing and testing it. Further, the web server logs
- clearly showed multiple POST requests being received by it from the
- same client usually with a few seconds of intervals between the
- consecutive requests. The comments seemed to have legitimate
- content. Since the duplicate copies would all have the same comment,
- I would arbitrarily pick one and publish it on my website. But I
- often wondered why on earth well meaning visitors would sometimes
- submit the same comment multiple times. For good measure? Perhaps!
- But still quite odd!
- </p>
- <h2 id="so-what-is-the-problem">So What's the Problem?<a href="#so-what-is-the-problem"></a></h2>
- <p>
- The mystery of duplicate comment submission remained a puzzle for
- several months. Then one day, one of the visitors to my website
- contacted me via Twitter messages to tell me that my comment form
- was broken and it was not working for him.
- </p>
- <p>
- The conversation began like this: "Hey! The comment form on your
- website seems to be broken. It says it has accepted my comment but I
- don't think it is doing that."
- </p>
- <p>
- I responded, "Hi! Thank you for contacting me about this issue. What
- do you mean it does not accept your comment? Do you see an error?"
- </p>
- <p>
- "There is no error. In fact, after submitting, I get a success
- message that says, 'Comment was submitted successfully. It may be
- published after review.'"
- </p>
- <p>
- "That sounds about right. So what's the problem?"
- </p>
- <p>
- In the meantime, I performed some testing at my end to find that the
- comment form appeared to be working fine with no apparent issues.
- Further, I found that there were multiple copies of his comment
- saved neatly on the server for me to review later and publish.
- </p>
- <p>
- Before I could share my findings, he continued, "Well! That success
- message appears almost instantly. It couldn't be storing my comment
- successfully that fast, could it?"
- </p>
- <p>
- That is when the mystery unfolded for me! The issue was that the
- comment form accepts the user's comment and returns a success
- message too soon for the user to believe that it could have possibly
- saved the comment. I have had a couple of other very similar
- conversations since then when a visitor contacted me via email or
- another means to double-check if my comment form was really working
- fine. In all of these cases, they were skeptical about the success
- message because it appeared much sooner than they expected.
- </p>
- <h2 id="bloated-expectations">Bloated Expectations<a href="#bloated-expectations"></a></h2>
- <p>
- Depending on where the visitor is located, the comment form on this
- website may take anywhere between 30 ms to 900 ms, and very rarely a
- little longer, to accept the user's comment, save it successfully,
- and then display a success message to the user. But apparently, a
- few hundred millseconds is too fast for many people to be able to
- trust that the comment application is actually doing its job. I
- presume that they have become so used to waiting for at least a
- second or more for dynamic pages to load that a web application that
- finishes its job in a few milliseconds appears to be fishy.
- </p>
- <p>
- I must clarify here that the duplicate comment submissions do not
- bother me at all. The duplicate comments I receive is a very small
- fraction of the total number of comments. I just find it interesting
- that users can mistrust a simple piece of software that does a
- simple thing in a reasonable amount of time. I had one visitor to my
- website even say, "I really was expecting a spinning wheel on the
- browser tab or some sort of progress indicator to be assured that it
- is saving my comment. The instant success message took me by
- surprise!" He felt nervous that his comment was not saved and
- resubmitted the comment again.
- </p>
- <p>
- As a result of these conversations, I have sometimes even wondered
- whether I should add some artificial delay in the comment
- application before responding with a success message to satisfy the
- expectations of people who are so used to the bloated web. Of
- course, I am not actually going to do that. I want to keep it
- simple. I do not like adding artificial restrictions to a simple
- piece of functionality. Further, I do not mind the duplicate comment
- submissions at all. However, I cannot help but remark that the users
- of the web today have become so comfortable with the bloated web
- that a simple web application without bells and whistles that is
- fast and responsive makes them nervous!
- </p>
- <h2 id="update">Update<a href="#update"></a></h2>
- <p>
- <strong>Update on 13 Mar 2022:</strong> Many commenters to this post
- have suggested that the issue here might not be the fast response of
- a successful comment application but instead the fact that the
- comment form elements remain intact even after the comment
- submission. In their opinion, merely displaying a success message
- may not be assuring enough. They further suggested that I should
- change the state of the form in some way on successful submission.
- Popular recommendations included disabling, clearing, or removing
- the form elements entirely on successful submission.
- </p>
- <p>
- These suggestions are valid of course. However, I also think that
- these suggestions reinforce the point of my blog post. Users of the
- web today are so used to these fancy features and restrictions that
- without them one feels unsure if the comment form application has
- really done what it is <em>literally</em> saying it has done.
- </p>
- <p>
- Do I really need to consider <em>artificially</em> clearing,
- disabling, or removing the form elements and thus removing the
- ability to edit a comment again and resubmit it (even if the user
- really so desires) with a single click of a button? What if someone
- wants to post another comment immediately after the first one? What
- if someone wants to edit their previous comment slightly and repost
- it? Do I need to force the user to hop through separate links and
- buttons to be able to do these simple things? "But every other
- website clears, disables, or removes the form elements," you might
- rightfully offer as a counterpoint. I know. I know. But why is it so
- that the "right" user experience nowadays involves artifically
- encumbering the user or hiding the user's own submitted text from
- themselves?
- </p>
- <p>
- In fact, in an earlier version of this website, the comment form
- application did disable the form elements on a successful comment
- submission. In an even older version of this website, a new page
- consisting only a success message appeared. However, visitors would
- still report their suspicion regarding the comment form doing its
- job to me. So I have observed the results of employing at least two
- of the measures suggested and they were still consistent with the
- reporters' claims that they find the instant success message from
- the application to be disconcerting.
- </p>
- <p>
- UX best practices notwithstanding, I do not want to hide the users'
- content from themselves after a successful form submission. Maybe
- they want to copy the message and keep it for themselves. Maybe they
- want to edit it again and repost it. I do not want to restrict any
- of these simple things. I also do not want the user to hop through
- another additional link or button to be able to do these things.
- Therefore, heeding some of the other advice I have received, I have
- now made two tiny changes to the comment form application that is
- consistent with its original spirit of simplicity, minimalism, and
- statelessness. I have moved the success message to the top of the
- response page. I have also added additional text in the success
- message that explains the submitted input has been left intact in
- case the submitter wants to copy it, or edit it and resubmit it.
- </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>
|