‹ BackHN Continuity

Thread

Improving site performance by shipping more CSS

96 points · 72 comments · torutofu

  1. efortis · · focus · HN ↗
    There's room for improvement still. Currently, the production build is using long-dev class names. e.g. `DirectoryContent-module__Box_3__gl6dE` could be compiled to a shorter hash like `gl6DE3a2`.

    If you use Vite:

      css: {
        modules: {
          generateScopedName: mode === 'production'
            ? '[hash:base64:8]'
            : '[name]__[local]___[hash:base64:5]',
          }
        }
    1. robin_reala · · focus · HN ↗
      Those class names surely gzip better than hashes over the wire?
      1. efortis · · focus · HN ↗
        Here's a comparison using `brotli --best` on my app.

           53K _long.css
           38K _short.css
        
           11K _long.css.br
          8.9K _short.css.br
        
        Both, dev and prod, have hashes because that's part of what CSS Modules uses to avoid collisions.

        Besides download size, smaller names improve parsing speed too.

        1. chrismorgan · · focus · HN ↗
          You could also drop the hash part and gain most of that improvement. Or module and hash and do better on compression (because the hash is high-entropy).

          Rudimentary experiment on <a href="https:&#x2F;&#x2F;github.githubassets.com&#x2F;assets&#x2F;te.1288ac5c9584fbf2.module.css" rel="nofollow">https:&#x2F;&#x2F;github.githubassets.com&#x2F;assets&#x2F;te.1288ac5c9584fbf2.m... on replacing &#x2F;(?&lt;module&gt;[A-Za-z0-9_-]+)__(?&lt;local&gt;[A-Za-z0-9_-]+)__(?&lt;hash&gt;[A-Za-z0-9_]{5})\b&#x2F;:

          ${module}__${local}__${hash} (original): 72967 raw, 10993 br.

          ${module}__${local}: 68459 raw, 8867 br.

          ${hash}: 48754 raw, 8189 br.

          ${local}: 52610 raw, 7927 br. (Now in practice a few of these are likely to need disambiguation, so it’s probably a tad smaller than realistic.)

          Frankly I think ${local} is the right target, with global disambiguation where necessary. For typical systems, I consider the hash approach to be foolish: its value is when interacting with unknown other styles, but when you’re compiling everything you should know everything, so you can disambiguate more selectively and succinctly&#x2F;compressibly, as JS build tools like Rollup do (in flattening modules with colliding names, you’ll get Foo, Foo$1, Foo$2, &amp;c.).

          1. efortis · · focus · HN ↗
            &gt; ${local} is the right target, with global disambiguation where necessary.

            How?

            ---

            Another approach is using base52 sequential names, such as `aa, ab, …`. I tried that a few years ago in Webpack, I don&#x27;t remember but there was an issue, IIRC they weren&#x27;t deterministic.

            1. chrismorgan · · focus · HN ↗
              Compile everything together and you know what names are used. I can’t comment on whether it’s easy or even possible with the specific toolchain in question, but the concept is very straightforward.
Open on Hacker News to reply ↗

Unofficial Hacker News client; not affiliated with Y Combinator.