URL: https://github.com/peterbe/minimalcss/pull/296#issuecomment-460392253

tl;dr; minimalcss 0.8.2 introduces a 20% post-processing optimization by lumping many CSS selectors to their parent CSS selectors as a pre-emptive cache.

In minimalcss the general core of it is that it downloads a DOM tree, as HTML, parses it and parses all the CSS stylesheets associated. These might be from <link ref="stylesheet"> or <style> tags.
Once the CSS stylesheets are turned into an AST it loops over each and every CSS selector and asks a simple question; "Does this CSS selector exist in the DOM?". The equivalent is to open your browser's Web Console and type:

>>> document.querySelectorAll('div.foo span.bar b').length > 0
false

For each of these lookups (which is done with cheerio by the way), minimalcss reduces the CSS, as an AST, and eventually spits the AST back out as a CSS string. The only problem is; it's slow. In the case of view-source:https://semantic-ui.com/ in the CSS it uses, there are 6,784 of them. What to do?

First of all, there isn't a lot you can do. This is the work that needs to be done. But one thing you can do is be smart about which selectors you look at and use a "decision cache" to pre-emptively draw conclusions. So, if this is what you have to check:

  1. #example .alternate.stripe
  2. #example .theming.stripe
  3. #example .solid .column p b
  4. #example .solid .column p

As you process the first one you extract that the parent CSS selector is #example and if that doesn't exist in the DOM, you can efficiently draw conclusion about all preceeding selectors that all start with #example .... Granted, if they call exist you will pay a penalty of doing an extra lookup. But that's the trade-off that this optimization is worth.

Check out the comments where I tested a bloated page that uses Semantic-UI before and after. Instead of doing 3,285 of these document.querySelector(selector) calls, it's now able too come to the exact same conclusion with just 1,563 lookups.

Sadly, the majority of the time spent processing lies in network I/O and other overheads but this work did reduce something that used to take 6.3s (median) too 5.1s (median).

Comments

Your email will never ever be published.

Previous:
Hooks tip! Avoid infinite recursion in React.useEffect() February 6, 2019 React, JavaScript
Next:
create-react-app, SCSS, and Bulmaswatch February 12, 2019 Web development, React, JavaScript
Related by category:
How to SSG a Vite SPA April 26, 2025 JavaScript, Web Performance
Switching from Next.js to Vite + wouter July 28, 2023 JavaScript, Node
fnm is much faster than nvm. December 28, 2023 Node
An ideal pattern to combine React Router with TanStack Query November 18, 2024 JavaScript
Related by keyword:
Premailer.io July 8, 2015 Python, Web development, AngularJS, JavaScript
mincss "Clears the junk out of your CSS" January 21, 2013 Python, Web development
How to use minimalcss without a server April 24, 2020 Web development, Node, JavaScript
CSS selector simplifier regular expression in JavaScript December 20, 2017 Web development, JavaScript