Skip to content

1.8.0 Usage data support, rules merge improvements and minifyBlock() function

Compare
Choose a tag to compare
@lahmatiy lahmatiy released this 24 Mar 12:42
· 286 commits to master since this release

The main feature of the release is usage data support. By default the optimizer doesn't know how CSS is using on markup and performs safe transformations only. But such knowledge allows to do much more.
CSSO doesn't collect any information about CSS using (that's other tools task) but can use usage data to perform filtering and better compression. Data can be provided via --usage option for CLI or usage option for minify() and compress() methods.

Filtering

Usage data can be used to filter selectors that contains something not in a white list. You can provide lists for tag names, class names or ids.

> cat example.css
.with { color: red; }
.usage.data { color: green; }
.we.can.do.more, .data { color: blue; }
.not.only.usage { color: yellow; }

> csso example.css
.with{color:red}.usage.data{color:green}.data,.we.can.do.more{color:#00f}.not.only.usage{color:#ff0}

> cat usage.json
{
    "classes": ["usage", "data"]
}

> csso example.css --usage usage.json
.usage.data{color:green}.data{color:#00f}

Scopes

CSS scope isolation solutions such as css-modules are becoming popular today. Scopes are similar to namespaces and defines lists of class names that exclusively used on some markup. This information allows the optimizer to move rulesets more agressive. Since it assumes selectors from different scopes can't to be matched on the same element. That leads to better ruleset merging.

In example we get better compression using scopes information (29 bytes extra saving).

> cat example.css
.module1-foo { color: red; }
.module1-bar { font-size: 1.5em; background: yellow; }

.module2-baz { color: red; }
.module2-qux { font-size: 1.5em; background: yellow; width: 50px; }

> csso example.css
.module1-foo{color:red}.module1-bar{font-size:1.5em;background:#ff0}.module2-baz{color:red}.module2-qux{font-size:1.5em;background:#ff0;width:50px}

> cat usage.json
{
    "scopes": [
        ["module1-foo", "module1-bar"],
        ["module2-baz", "module2-qux"]
    ]
}

> csso example.css --usage usage.json
.module1-foo,.module2-baz{color:red}.module1-bar,.module2-qux{font-size:1.5em;background:#ff0}.module2-qux{width:50px}

Compression improvement with this feature depends on project structure. For a project in which we tested the feature, it gives 25-38% CSS size reduction compared to result without using usage data (the project uses its own CSS module isolation solution).

See more detail about feature in readme.

minifyBlock()

Some tools are using CSSO not only for stylesheet compression but also for style attribute compression. If use minify() method for this task it raises a parse error. So tool's authors do something like that:

var csso = require('csso');

function compressStyleAttributeContent(options) {
    var tmp = '.dummy{' + style + '}';
    var compressed = csso.minify(tmp, options);

    return compressed.replace(/^\.dummy\{|\}$/);
}

compressStyleAttributeContent('color: rgba(255, 0, 0, 1); color: yellow', options);
// > 'color:#ff0'

Now it's all can be replaced for minifyBlock() function. No more hacks!

var csso = require('csso');

css.minifyBlock('color: rgba(255, 0, 0, 1); color: yellow', options);
// > 'color:#ff0'

Changes

  • Usage data support:
    • Filter rulesets by tag names, class names and ids white lists.
    • More aggressive ruleset moving using class name scopes information.
    • New CLI option --usage to pass usage data file.
  • Improve initial ruleset merge
    • Change order of ruleset processing, now it's left to right. Previously unmerged rulesets may prevent lookup and other rulesets merge.
    • Difference in pseudo signature just prevents ruleset merging, but don't stop lookup.
    • Simplify block comparison (performance).
  • New method csso.minifyBlock() for css block compression (e.g. style attribute content).
  • Ruleset merge improvement: at-rules with block (like @media or @supports) now can be skipped during ruleset merge lookup if doesn't contain something prevents it.
  • FIX: Add negation (:not()) to pseudo signature to avoid unsafe merge (old browsers doesn't support it).
  • FIX: Check nested parts of value when compute compatibility. It fixes unsafe property merging.