[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)