Releases: css/csso
1.5.4
1.5.3
1.5.2
1.5.1
- ensure
-
is not used as an identifier in attribute selectors (thanks to @mathiasbynens) - fix broken
justDoIt()
function - various small fixes
1.5.0
The main changes of this release are about compressor. It significant refactored in two aspects: code simplicity and performance. Also a new AST format for compressor was introduced.
Let's start with clarification on the new AST format. As you may know csso
uses gonzales
to parse CSS to get AST. In the past it was one of fastest detailed CSS parsers written in JavaScript. But now gonzales
isn't fast enough and hasn't support for some new things that were added to CSS last years. Further more gonzales
uses arrays to describe AST nodes that isn't verbose, slow and expensive for memory. Also its format has several design mistakes and unsuitable for transformations as well.
Therefore, the replacement of the parser became obvious. But it isn't so easy since every single part of csso
depends on AST format. Another problem is there is no suitable detailed CSS parser that can be a replacement for gonzales
. So I have started working on this sort of parser a сouple of months ago. But still a lot of work to be done. Until that I decided to do first step for parser replacing by introducing new AST format (for now for internal usage only). Currently gonzales
is used for getting initial AST which after that is converted into internal format. Theoretically it's possible to write AST convertors for other parsers too. Thus csso
became less dependent on the parser.
Actually new format appeared in the middle of refactoring to simplify code and improve readability. But first tests showed performance boost too despite AST conversion overhead. That was the sign that we are on the right way.
Earlier source code of compressor was too complicated and was located in a single file. Now it is splitted into simple modules grouped by phase of processing: cleaning, compressing and restructuring. It makes dealing with compressor's source code much easier. Moreover, beside improved readability, the new AST format helped to simplify the source code since this format uses objects instead of arrays to describe AST nodes, has no redundant things and much more suitable for transformations.
Before we talk about performance, let's look at comparison table first (the table is based on css-minification-benchmark):
Library | 1.4.4 | 1.5.0 | Diff |
---|---|---|---|
960.css (9989 bytes) | 142.71 ms | 116.89 ms | 1.2 |
animate.css (71088 bytes) | 432.12 ms | 290.27 ms | 1.5 |
blueprint.css (17422 bytes) | 179.81 ms | 150.66 ms | 1.2 |
bootstrap.css (147427 bytes) | 1022.78 ms | 547.48 ms | 1.9 |
font-awesome.css (28746 bytes) | 173.37 ms | 93.74 ms | 1.8 |
foundation.css (200341 bytes) | 1308.3 ms | 648.62 ms | 2.0 |
gumby.css (167123 bytes) | 1537.72 ms | 452.67 ms | 3.4 |
inuit.css (53049 bytes) | 160.17 ms | 103.83 ms | 1.5 |
normalize.css (7707 bytes) | 10.73 ms | 9.58 ms | 1.1 |
oocss.css (40151 bytes) | 111.71 ms | 75.98 ms | 1.5 |
pure.css (31318 bytes) | 132.55 ms | 76.67 ms | 1.7 |
reset.css (1092 bytes) | 24.15 ms | 7.2 ms | 3.4 |
As you can see, csso
1.5 is about 1.2–3.4 times faster than previous version. Take in account that those numbers contain time of all operations, i.e. parsing, compression and translation. In 1.4
compression takes more than ¾ of total time, but the new version takes less than a half of it. In fact compression become much faster than changes in total time because parsing takes significant time (one more reason to change parser) and has not changed.
As was mentioned above, some part of the performance boost due new AST format. It's not the single optimisation. Restructuring algorithms were also improved, redundant calculations and actions were removed, creating and copying of data structures was reduced, various caches and indexes are using now, some heuristics based on CSS specifics were used. Also final restructuring steps perform without a loop now. This loop was very expensive because snapshots (AST translating to string) were made in the beginning and in the end of each iteration and compared to check that iteration has good progress. It led to a lot of memory consumption and , even to processing freeze on large files. For example test file (3.7Mb) in issue #201 was never processed whereas now it takes about 12 seconds to be done (not so good but better than infinity). It is also worth noting that memory consumption has also been reduced by more than a half.
It's not the end of the compressor refactoring. The restructuring algorithms still need to be replaced for better ones that produce better results. More optimisation could be done when the parser will provide more details about CSS structure. So new improvements are coming.
Change log
Parser
- attach minus to number
Compressor
- split code base into small modules and related refactoring
- introduce internal AST format for compressor (
gonzales
→internal
andinternal
→gonzales
convertors, walkers, translator) - various optimizations: no snapshots, using caches and indexes
- sort selectors, merge selectors in alphabet order
- compute selector's specificity
- better ruleset restructuring, improve compression of partially equal blocks
- better ruleset merge – not only closest but also disjoined by other rulesets when safe
- join
@media
with same query outputAst
– new option to specify output AST format (gonzales
by default for backward compatibility)- remove quotes surrounding attribute values in attribute selectors when possible (issue #73)
- replace
from
→0%
and100%
→to
at@keyframes
(#205) - prevent partial merge of rulesets at
@keyframes
(#80, #197)
API
- walker for
gonzales
AST was implemented
CLI
- new option
--stat
(output stat instderr
) - new optional parameter
level
for--debug
option
1.4.4
1.4.3
1.4.2
- allow spaces between
progid:
and rest part of value for IE'sfilter
property asautoprefixer
generates this kind of code (#249) - fixes for Windows:
- correct processing of new lines
- normalize file content in test suite before comparing
- fixes to work in strict mode (#252)
- init compressor dictionaries for every css block (#248, #251)
- bump uglify-js version
1.4.1
- allow merge for
display
property (#167, #244) - more accurate
rect
(clip
property value) merge - fix typo when specifying options in cli (thanks to @Taritsyn)
- fix safe unit values merge with keyword values (#244)
- fix wrong descendant combinator removal (#246)
- build browser version on
prepublish
(thanks to @silentroach) - parser: store whitespaces as single token (performance and reduce memory consumption)
1.4
Back project to life. Changed files structure, cleaned up and refactored most of sources. Closed 60+ issues.
Common
- single code base (no more
src
folder) - build browser version with
browserify
(no moremake
, andweb
folder), browser version is available atdist/csso-browser.js
- main file is
lib/index.js
now - minimal
node.js
version is0.12
now - restrict file list to publish on
npm
(no more useless folders and files in package) - add
jscs
to control code style - automate
gh-pages
update - util functions reworked
- translator reworked
- test suite reworked
- compressor refactored
- initial parser refactoring
API
- new method
minify(src, options)
, options:restructuring
– if set tofalse
, disable structure optimisations (true
by default)debug
- outputs intermediate state of CSS during compression (false
by default)
- deprecate
justDoIt()
method (useminify
instead) - rename
treeToString()
method tostringify()
- drop
printTree()
method - AST node info
column
andoffset
addedln
renamed toline
- fix line counting across multiple files and input with CR LF (#147)
CLI
- completely reworked, use clap to parse argv
- add support for input from stdin (#128)
- drop undocumented and obsoleted options
--rule
and--parser
(suppose nobody use it) - drop
-off
alias for--restructure-off
as incorrect (only one letter options should starts with single-
) - new option
--debug
that reflecting tooptions.debug
forminify
Parsing and optimizations
- keep all exclamation comments (#194)
- add
/deep/
combinator support (#209) - attribute selector
- color
- support all css/html colors
- convert
hsla
torgba
andhls
torgb
- convert
rgba
with 1 as alpha value torgb
(#122) - interpolate
rgb
andrgba
percentage values to absolute values - replace percentage values in
rgba
for normalized/interpolated values - lowercase hex colors and color names (#169)
- fix color minification when hex value replaced for color name (#176)
- fit rgb values to 0..255 range (#181)
- calc
- don't remove units in
flex
property as it could change value meaning (#200) - don't merge
\9
hack values (#231) - merge property values only if they have the same functions (#150, #227)
- don't merge property values with some sort of units (#140, #161)
- fix
!important
issue fortop-right-bottom-left
properties (#189) - fix
top-right-bottom-left
properties merge (#139, #175) - support for unicode-range (#148)
- don't crash on ruleset with no selector (#135)
- tolerant to class names that starts with digit (#99, #105)
- fix background compressing (#170)
Small personal sidenote
We have been using csso
in our building process for years. Not only as CSS compress utility, but also as a parser to get AST, transform it and pass to csso
for compression.
All those years it worked stable enough and various bugs usually were not an issue. I have even rewritten some util functions to use it instead of csso
functions. But project has no maintainer for years. In spite of the opinion that csso
is dead, it has its own audience and number of downloads continues to grow. It's sad that many issues were left with no attention. Moreover I wanted to improve it to make CSS compression results much better and predictable.
That's why I've decided to change the situation. I’m happy that project's owners gave me this opportunity. I became maintainer of csso
and started bringing it back to life.
As a first steps I've changed files structure, cleaned up and refactored most of sources. Now it has single code base, with reworked test suite, jscs
for code style check, browserify
to build the bundle, automated gh-pages
publishing etc. All aim to ensure that nothing prevents us to move forward.
After initial refactoring and a bunch of bug fixes, it's now clear to me that all parts of csso
need to be reworked. First of all compressor's struсtural optimization algorithms should be replaced for others, that are safer, faster and more efficient. Parser should become compliant to standards, with support for new CSS features and more predictable. When this is done, we can try new structural optimizations, that no one has tried before. That is the main reason why I've decided to work on csso
.
Stay tuned!