[HN Gopher] Parcel CSS: A new CSS parser, compiler, and minifier ___________________________________________________________________ Parcel CSS: A new CSS parser, compiler, and minifier Author : Lapz Score : 211 points Date : 2022-01-12 17:05 UTC (5 hours ago) (HTM) web link (parceljs.org) (TXT) w3m dump (parceljs.org) | systemvoltage wrote: | Unrelated but regarding SCSS/SASS: I am curious, why did we | invent a new syntax for scss instead of writing a library in | Python or Go that maps data-objects to CSS classes? You have full | access to a proper programming language instead of this new DSL | we need to learn. I tried searching for it but no luck, any | reason why we don't do this? | eatonphil wrote: | It's called interoperable css [0] or css modules [1]. | | [0] https://github.com/css-modules/icss | | [1] https://github.com/css-modules/css-modules | iaml wrote: | > I am curious, why did we invent a new syntax for scss instead | of writing a library in Python or Go that maps data-objects to | CSS classes? | | I mean, if using js/ts is not beneath you I'm pretty sure any | css-in-js solution fits the bill. | assemblylang wrote: | no_wizard wrote: | This is amazing! Seen a lot of work around Rust and JS / JSX / TS | / TSX (notably SWC[0] is moving to be a Rust based version of | Babel) not so much around CSS. | | My genunine hope is this will replace PostCSS sooner rather than | later. PostCSS isn't the most performant thing I've worked with, | and a lot of plugins for PostCSS rely on doing multiple passes at | the AST, they can slow down significantly as a result | | For that however, we will need some kind of plugin system. I know | the SWC[0] project has had some struggles with this as their | current JS API relies on serializing the AST back and forth. I | wonder if this forgoes a JS API entirely or if that is something | planned for say 1.5? | | [0]: https://swc.rs/ | devongovett wrote: | Hi, author of Parcel CSS here. | | I have been thinking about implementing the CSS OM spec as the | JS API. This is the same API that browsers expose for | manipulating stylesheets. The advantage of this is that we | don't need to invent something custom. Still thinking through | options. https://github.com/parcel-bundler/parcel-css/issues/5 | | That said, I think I'd want to keep the use cases for JS | plugins limited, because it will affect performance | significantly. So, if it's something that exists in an official | CSS spec somewhere (even if draft), or a really common | transformation, it should be implemented in Rust. An example of | this is the support for the CSS nesting spec. Ideally, we'd try | to keep the amount of custom syntax being invented around CSS | to a minimum and stick to standard CSS syntax wherever possible | though. | jafitc wrote: | Is this something that can run in browser Workers via wasm or | other means? | | Most of CSS OM is already implemented in Javascript which can | come in handy for this project: | | https://github.com/NV/CSSOM | | https://github.com/jsdom/cssstyle | | (both of which jsdom use internally. cssstyle is a kind of | updated version for some parts of CSSOM) | devongovett wrote: | Yes, there is a WASM build used by the demo: | https://parcel-css.vercel.app | | Not sure if we could reuse these packages though, since | we'd need to expose an API from Rust to JS anyway. | no_wizard wrote: | Separate question, that may be seemingly unrelated however | I'm curious. | | How did you kinda "learn" how to read these specs | effectively? I can read them, and I think I can _reasonably_ | understand them, however I feel like I have little confidence | in saying _yes I get this_. | | Is there anything you point to that helps? Tips or | recommendations? | | I'm trying to learn how to parse these standards docs better | myself. | andrei_says_ wrote: | Does this include dart scss processing? | TameAntelope wrote: | I was just looking at Parcel a week or so ago to replace the | stagnated Snowpack project for our frontend. | | Should I just stop trying to avoid it and just use Webpack 5, or | can I actually rely on Parcel in a way I couldn't Snowpack? | | I just want to bundle my React app, I'm not trying to do anything | special... | annoyingmous wrote: | 01acheru wrote: | Parcel is becoming my go-to choice most of the time now. I've | migrated some apps out of CRA, pure Webpack and Snowpack to it | and I need to say it was incredible. | | Some minor issues with HMR on one of those projects I still | can't figure out. Anyway having something that works, with JSX, | with TS, really fast, in just 2/3 really simple steps is | amazing! You don't even need to turn your brain on. | | My two cents. | ReleaseCandidat wrote: | I used Parcel for about a week a month ago. Couldn't get the | HTTPS server to use my certificate and key and would have | needed to write a plugin so that it wouldn't rename favicons | and delete files not mentioned in the HTML file. | | So, Esbuild for 'no configuration' as it is significantly | faster than Parcel and Webpack for more complex stuff. | CognitiveLens wrote: | Parcel has been around for awhile, and the project currently | has a lot of activity - I've made the call to migrate an old | create-react-app project to Parcel 2 and in general it is going | well. | | The nice thing about Parcel is that it is intentionally low- | config with relatively intuitive defaults, which tells me that | it wouldn't be terribly difficult to move to a different | bundler in the future. Webpack has gotten better, but you can | quickly end up with a _lot_ of Webpack-specific config that | makes future migrations hard. | | That said, optimizing for future migrations shouldn't generally | be your #1 priority - I also like Parcel's speed, and new | things like ParcelCSS just validate that further. | nawgz wrote: | Snowpack, ESBuild, ..., all promised us nice frontend compiles, | yet I still turn to Webpack every time I actually want | everything to work - you always hit roadblocks you can't solve | in these other tools. | | That'd be my recommendation to you, still, sadly. | armchairhacker wrote: | I recommend Vite. I use ESBuild in some libraries but it has | a learning curve. Vite's experience is similar to Webpack. | omnimus wrote: | Not my experience. Both esbuild and vite have been great for | my usecases. | no_way wrote: | Use Vite instead, it has very nice developer experience. | Webpack is a "legacy" bundler, while it is supported, is | shouldn't really be used in new projects if you really value | your sanity. | nicoburns wrote: | I'd argue that Vite's still pretty immature. It's great if | you can stick within what works with it, but webpack is still | the gold standard in terms of compatibility and features, and | I suspect that will be the case for another couple of years | while the native code bundlers (esbuild, swc, etc) catch up | with their JS counterparts. | krono wrote: | Webpack is under active development though, nothing legacy | about it as far as I'm aware. Are you referring to abandoned | third-party plugins maybe? | | Vite and all the other bundlers are really awesome, but | Webpack's strenght - and I think this may also be the root of | the issues you seem to be having with the tool - is that | there's almost no magic and barely any handholding. Freedom | and reliability at the cost of having to build your own | configuration (it's just dumping plugin config objects in an | array, really not difficult). | 01acheru wrote: | > it's just dumping plugin config objects in an array, | really not difficult | | Until you eject a CRA :) | krono wrote: | Which is the cherry on top for those types of self- | chastisement fetishists who willingly put themselves at | the mercy of CRA ;-) | no_way wrote: | I have done manual configs from scratch in Rollup, even | wrote bunch of plugins for stuff like custom css class | minifying and web worker support, so no I don't need | handholding :) Setting it all up was even fun, everything | was well documented and clear, with Webpack on the other | hand, you only have fun if you like pain. | tiborsaas wrote: | > Webpack is a "legacy" bundler | | How did you end up with this assessment? I'm not a fan | either, but it's still very popular, I doubt it will go away | in the next 5 years. | no_way wrote: | It won't go away, it will still be supported and used for | many years, but majority of new projects today won't use | it. Brief history: Rollup dramatically improved bundler | plugin and ES modules situation, then came new super fast | bundlers like Esbuild and finally solutions combining both | like Vite. Webpack is still playing catch up with that. | There is literally zero reasons to choose clunky, slow | Webpack configs, while alternatives exist, unless you have | a legacy codebase and migrating is not an option. | pferdone wrote: | I seriously don't get the hatred Webpack receives. Calling it | legacy when it introduced stuff like module federation is | unfair to say the least. Just because a lot of people use CRA | or some "zero config" bundler, or because esbuild etc are | picking up momentum, doesn't mean it's bad. The documentation | is actually really good IMO. | samhuk wrote: | I have been using esbuild for a while, and I can say that it's | looking like a huge improvement over webpack, snowpack, vite, | etc. | | I made a web app starter that uses esbuild to bundle a react- | redux app [0] and my experience was very positive of the | bundler. | | [0] https://github.com/samhuk/tree-starter | dgellow wrote: | That's awesome, great job! | Semiapies wrote: | The syntax lowering and modules handling might be really nice. | Maybe even the tree-shaking. Minification, thought, especially | with this level of parsing, just seems like an elaborate waste of | effort if the web server is set to gzip the final CSS file, | anyway. | throw10920 wrote: | After I saw the title, I thought "oh, it seems to kind of occupy | the same space as esbuild, but for CSS. I wonder if the devs gave | any thought to performance?" Then I clicked the link and saw that | there a _direct comparison_ with esbuild, with Parcel being 3x | faster on a large real-world benchmark (Bootstrap 4). | | This is really impressive. Although Rust tooling is rather | suboptimal, Rust _programs_ seems to have quite the performance | edge. I 'll take the RESF any day as long as it means getting | away from ultra-heavy webtech everywhere. | chronogram wrote: | In the playground, why does 'yellow' get converted to '#ff0' but | 'green' remains 'green'? | pastelsky wrote: | Because the hex for green (#00ff00) needs more letters than | using the named color. | dymk wrote: | That's an... interesting optimization, and one that might | make sense if you only care about byte size, but intuition | (which might be wrong!) tells me that this will be more | expensive (especially if it saves only one or two bytes). | | I'd bet that browsers can more quickly parse a string like | '0x00ff00' into its internal color representation than it can | parse the string 'green'. It's probably faster to check for a | '0x' prefix and convert hex-encoded ASCII to u8 values, than | it is to normalize the string & do a lookup in a dictionary | of 147 CSS3 color names, when taking into account the extra | two bytes that need to be transferred. | assemblylang wrote: | pawelmurias wrote: | I doubt that difference it takes to parse green vs a | 0x00ff00 is at all significant. It only should happen once | per page load. | gampleman wrote: | Don't know, but I wouldn't be surprised if the browser | first tried a dict lookup (which is super fast) and only | then tried to actually parse hex the string. | CognitiveLens wrote: | I don't get the sense that runtime CSS parsing is really | much of a concern - it's more about build speed and asset | size - since 'green' might be used hundreds of times in a | large CSS bundle, the optimization might make sense even | with an imperceptible speed cost in the browser. | rattray wrote: | I don't have intuition here, but perhaps transferring two | bytes over a slow network takes longer than the string | normalization and dictionary lookup? | marcosdumay wrote: | > one that might make sense if you only care about byte | size | | A minimizer should care a lot abut size. I'm not sure what | would be faster, but the difference must be minimal anyway, | so it's safe to focus on your default concern. | robocat wrote: | More importantly, I would expect #00ff00 to compress better | than green, because it would usually make the CSS file more | predictably repetitive. Reducing network bytes is usually | very important for speeding up loading (at least it is in | the boondocks of the internet - out at the rim of the | world). | ry4nolson wrote: | Someone else mentioned this already but "green" is not | #00ff00. Tt's #008000. | [deleted] | rawling wrote: | Wouldn't that shorten to #0f0? But "green" is #008000, which | doesn't shorten? | chronogram wrote: | Ah thanks, I assumed '#0f0' as well. I guess it is length | based then. | zamadatix wrote: | Hmm I wonder which approach is actually better overall when | it comes to content-encoding like their own site uses | (brotli compression) or client side parsing performance. | It's all probably a bit off into the weeds over something | like 0.05% performance though. | davidhariri wrote: | Parcel is a great project that has made it much quicker to | develop a SPA. This only furthers my sense of joy for it. | sfvisser wrote: | What does it mean to compile CSS? Pack multiple files into one? | Resolve and inline variables? Convert nested rules into flat CSS? | Something else? | | I'm really not sure. | [deleted] | eatonphil wrote: | Elitism about the term "compiler" aside, I've been reading | through The History of the FORTRAN Programming Language and | funnily enough compile in those historic CS contexts just meant | what "to compile" means in English: merging things together. | It's an interesting read whatever the case. | | [0] https://www.goodreads.com/book/show/52320048-abstracting- | awa... | sfvisser wrote: | This is not about elitism about terminology, but about | sloppiness in using well established words in a specific | context to mean something new. It happens rather frequently | in the frontend world - which I'm sometimes a part of - and | it's incredibly confusing to all of us. | eatonphil wrote: | I write frontend code and backend code and do compiler | stuff for fun and I don't find it confusing. "Compiler" | means completely separate things in so many contexts that I | get the general picture and always need to look deeper to | truly understand. Just because it's a generic term doesn't | mean anyone should not be allowed to use it IMO. | JonathonW wrote: | > In addition to minification, Parcel CSS handles compiling CSS | modules, tree shaking, automatically adding and removing vendor | prefixes for your browser targets, and transpiling modern CSS | features like nesting, logical properties, level 4 color | syntax, and much more. | [deleted] | codebeaker wrote: | Had you taken the time to open the link, the 2nd paragraph | states their capabilities succinctly: | | > Parcel CSS has significantly better performance than existing | tools, while also improving minification quality. In addition | to minification, Parcel CSS handles compiling CSS modules, tree | shaking, automatically adding and removing vendor prefixes for | your browser targets, and transpiling modern CSS features like | nesting, logical properties, level 4 color syntax, and much | more. | sfvisser wrote: | I've obviously read that. Most of those features are what we | used to call CSS pre-processors, but I'll happily call that | compilation if that's a thing now. | rattray wrote: | It wasn't obvious to me that you had read that paragraph. | have_faith wrote: | It's in the first couple paragraphs | | > Parcel CSS handles compiling CSS modules, tree shaking, | automatically adding and removing vendor prefixes for your | browser targets, and transpiling modern CSS features like | nesting, logical properties, level 4 color syntax, and much | more. | emrah wrote: | Its GitHub repo calls it a "transformer" rather than a | compiler. | | https://parceljs.org/features/plugins/#transformers | aarchi wrote: | > Parcel CSS is based on the cssparser[0] Rust crate, a browser- | grade CSS tokenizer created by Mozilla and used in Firefox. This | provides a solid foundation, including tokenization and basic | parsing. However, it does not interpret any CSS properties or at | rules. That's where Parcel CSS comes in. It handles parsing each | individual rule and property value, as well as minification, | compilation, and printing back to CSS. | | https://github.com/servo/rust-cssparser | [deleted] | kevincox wrote: | It's really nice to see browser components being able to be | reused easily rather than a bunch of half-assed parsers. | mikepurvis wrote: | Nice too that it's a compiled language, so you get the end | tool in a nice static binary. As a non-Node dev, I hate the | experience of hacking on some project and having to install a | giant pool of NPM stuff just to run some minifier or linter. | Hound is an example of this-- the guts of the project are | golang, but it has a frontend that uses webpack, jest, etc: | https://github.com/hound-search/hound | | Which is fine, I guess; definitely use the right tool for the | job. And maybe Node developers hate finding my Python | projects and needing to set up a virtualenv to run them in. | But all the same, I approve a direction where more of this | kind of tooling is available without a build-time Node | dependency. | hinkley wrote: | Agreed. If cssparser blows chunks on your css then at least | you know that will probably break some of your user agents | too, rather than the game of "is my tool broken or am I?" | tiffanyh wrote: | Why is a product written in Rust have "JS" (javascript) in its | URL name? | | I nearly didn't look at this because I didn't want another | javascript dependance in my pipeline. | hbn wrote: | It seems Parcel CSS is a project from the creators of Parcel | JS, which is a build tool. The URL isn't linking to the top- | level page on the domain | habitue wrote: | For some reason I trust minifier / compiler benchmarks way more | than I trust DB benchmarks. I wonder why that is? | | Maybe I expect DB workloads to be much more varied so benchmarks | are less representative. Whereas with minifying you can run it | against some large project and expect it'll reflect your real | world experience | swagatkonchada wrote: | I feel stupid asking this question, but isn't the browser that | parses css? i understand minifying css, but what does parcel's | css parsing refer to? | mbb70 wrote: | It parses the css so it can improve the minification, for | example converting 'margin: 4px 4px 4px 4px' into 'margin:4px' | yosamino wrote: | To do the job of minifying, this minifyer first reads the CSS | file into an internal datastructure. That process is called | parsing. | | All the minifying operations are done on that internal | datastructure. | | Then it writes it out again into a textfile, ready for the | browser to parse it again - hopefully the minifying step made | it a bit easier for the browser to parse this minified CSS. ___________________________________________________________________ (page generated 2022-01-12 23:00 UTC)