6 ms·
Show HN: DropCSS – A simple, thorough and fast unused-CSS cleaner
- leeoniya 8y agoHi HN, I put this together when looking to replace Purgecss in my build chain due to its numerous and unresolved/unresolvable correctness deficiencies. TL;DR: - Tiny API, ~60 LOC + 3 small deps - Does not process `<script>` or JS - Smaller and more thorough than Purgecss, UnCSS, PurifyCSS - Perf: 2.0x UnCSS, 1.1x PurifyCSS, 0.4x Purgecss
- owens99 8y agoNice work! Will give it a try.
- buu700 8y agoDoes (or will) this support SCSS, and Angular HTML, and JavaScript/TypeScript/JSX? I'm on a project right now where a tool like that will be immensely helpful pretty soon.
- leeoniya 8y agomost definitely not. at least not in the core. the aim is to stay simple and target the common baseline; there are ~1e6 css and html supersets with existing tools to output plain html and css. surely it's not difficult to glue the subset you need together. as an aside, i've come to dislike scss and much prefer to maintain my stylesheets in plain js, without awkward looping constructs, conditionals, variables, "mixins", etc. all of this is an already-solved problem with es modules and the language i already use: js. check out: https://github.com/cssobj/cssobj https://github.com/cssobj/cssobj https://github.com/cssobj/cssobj-plugin-gencss https://github.com/cssobj/cssobj-plugin-gencss
- amoerie 8y agoWhat about dynamically changing HTML? Modal dialogs, dynamically loaded divs (depending on access rights), etc. Unless your css is only ever loaded when the corresponding HTML is, this is going to flag a lot of false positives..
- leeoniya 8y agoyep, you need to keep a whitelist. i made a 10-liner plugin for css-obj (see my other comment) which i use to mark certain selectors with "!keep" which populates my per-page whitelists during initial css blob gen. if most of your classes are dynamically applied or most markup is missing then this type of tool is probably not for you, especially if you have no good way of html-ifying enough state variations to keep your whitelist managable. FWIW, i run an SSR'd ecommerce site (with modals and a quite a bit of other dynamic bits) and while whitelisting needs to be maintained, the resulting list is fewer than 30 items and basically static. the items are regex and some cover multiple/related selectors. an improvement to this project might be to add inline ignore rules like purgecss does. eg /* nodrop * /
- bigbadgoose 8y agoOK, what all these tools have not exhibited so far is upstream optimization of source generator, ie scss. Dream scenario: 1/ run against generated output via url submission, 2/ receive optimized output, 3/ point at source generator tree, 4/ receive suggested source diffs Lucid dream scenario: point at repository, receive optimized source diff suggestions on a per-file basis
- leeoniya 8y ago> 4/ receive suggested source diffs. most of the removed css isnt necessarily useless globally, it's just useless in context. eg a shared bootstrap css grid will be pruned differently on different pages, but there's no single "suggestion" that can be used to modify that shared initial grid. for css that's leftover by accident that should actually be removed from the source, i agree. but how will you discern the first scenario from the second?
- bigbadgoose 8y agoPer-group (URLs that operate within a 10% optimization range) cached css, generated by source tree + crawl + ongoing visit data? Edit, also pls send me a pony. Optimzations have a few audiences, the primaries of which are the visitor and the developer. Source tree prunes ("developer audience") not addressed in my off-the-cuff pipe dream above
- err4nt 8y agoCSS-blocks.com is the closest high-quality tool like this, but it's approach is slightly different, it doesn't work against any page, but for this approach it's by far the best quality and most powerful tool like this right now. And, it's made by one of the maintainers of Sass
- JensRex 8y agoI wish there was something like this not written in JavaScript.
- leeoniya 8y agoi'm sure there will be soon enough. i kind of laughed to myself when calling it "fast" since it takes 175ms to process ~45 KB of data :D. in a compiled language (or wasm) it would no doubt be an order of magnitude faster.
- postalrat 8y agoWhy is wasm faster than javascript? Can't the browser compile javascript to something equivalent?
- Theodores 8y agoVery nice tool. Small request. Can you use your knowledge of AST etc. to write another small 60 line script that just counts the amount of style rules in a CSS file? I have tried this and not been able to do a good job of it, media queries, CSS variables and other things have thrown me off and I think you are coming from a better starting point for this 'simple task'. Lines of code is not a useful metric with CSS and counting rules is not so simple as parsing is really a browser thing.
- leeoniya 8y agoby 'style rules' do you mean selectors or properties/values?
- Theodores 8y agoYes, just the amount of selectors. Properties/values is another metric worth knowing. I think that getting a number for both these metrics in the stylesheets rather than the page currently viewed is more useful if you are working on a site. As well as the stylesheets that are external the rules in an embedded stylesheet are useful. My ideal tool takes a page and gets those metrics from attached stylesheets as well as the inline stylesheets, with inline styles totalled up too. I have had a go at this using DomDocument PHP but took a guess at the rules based on the total count of '{' - terrible hack, but okay for ballpark figures. I would prefer to be able to do it properly, but I have not got anywhere trying to do it the node way. I didn't even know about CSSTree/AST.
- leeoniya 8y agothe main loop [1] already only visits "Rule" blocks, so you can just stick a counter in there, taking care to split combinator selectors on "," as i do, and add them up. [1] https://github.com/leeoniya/dropcss/blob/master/src/dropcss.js#L23-L24 https://github.com/leeoniya/dropcss/blob/master/src/dropcss....
- Theodores 8y ago
- adrianhel 8y agoThe fact that this is even needed is why I like CSS-in-JS.
- leeoniya 8y agoyou might still need it if you plan to use third party css libs, but not wholesale.
- jhabdas 8y agoVery pithy, Leon. What made you think to write this? P.s. When you slightly tweak MIT code you need to include the copyright and notice in your license, or ask the copyright holder to switch to 0BSD.
- leeoniya 8y ago> What made you think to write this? https://news.ycombinator.com/item?id=19469082 https://news.ycombinator.com/item?id=19469082 also, i wanted to see how fast something like this would be if i pulled together all libs that advertise/prove themselves to be "fastest" in their respective responsibilities amongst similar competing libs. > P.s. When you slightly tweak MIT code you need to include the copyright and notice in your license, or ask the copyright holder to switch to 0BSD. thanks, good to know. on the other hand, that adapter is so trivial that i don't think it quite warrants it. there are only so many ways to implement it against that small api surface. anyhow, first i want to see where the whole situation ends up: https://github.com/nrkn/css-select-browser-adapter/pull/3 https://github.com/nrkn/css-select-browser-adapter/pull/3 https://github.com/fb55/css-select/issues/118 https://github.com/fb55/css-select/issues/118 i'm also glad that this [1] got merged and released quickly :) [1] https://github.com/taoqf/node-html-parser/pull/5 https://github.com/taoqf/node-html-parser/pull/5
- tyingq 8y agoThe css/js coverage tab in Chrome's developer tools is also pretty neat: https://developers.google.com/web/updates/images/2017/04/coverage.png https://developers.google.com/web/updates/images/2017/04/cov... It drills down into the files, and there's a toggle to unminify: https://www.vojtechruzicka.com/static/911b02bfd910c9a689e363de64a2e8c0/17624/per-line-coverage.png https://www.vojtechruzicka.com/static/911b02bfd910c9a689e363...
- leeoniya 8y agoyep, that's where i got the unused bytes stats from