silbinarywolf / proposal-fel

FEL Programming Language Design Documents
3 stars 0 forks source link

Initial Thoughts #6

Open jerricco opened 5 years ago

jerricco commented 5 years ago

Preface

So I've been using Node-based JS build tools for about 3 years now. It's become a pretty graceful node-cli-type-application to orchestrate several tools rather than rely on the dependency hell that Grunt or Gulp foists upon you for the luxury of a sugary single build script.

I can definitely appreciate an effort to provide a more one-size-fits-all solution for the CSS/HTML/JS disparities. Judging from the success of Typescript (and from what you touched on in the proposal), the key is a light-touch approach where the tool can wrap trivially around existing projects and allow gradual migrations. I am aware JS is not mentioned much in the scope of this document, and I'll omit it mostly from my initial points to keep the starting scope tight.

Overall Impressions

I'll include this section as an dictum of my understanding of what is being proposed:

Giant Mess of Thoughts

There's definitely a slow part of CSS preprocessing.

It needs to be blazing fast. CSS preprocessors like SASS aren’t very complex but seem to compile significantly slower than other build tools like the TypeScript compiler

SASS may be a weird example since it's entire compiler ecosystem consists of libSass, which is a Rubygem (IIRC) and is painfully slow. That being said, LESS and Stylus seem to suffer from similar problems, most likely also compiling from a slower interpreted language.

My tool-chains for CSS however always seem to consist of:

optionally strip CSS with webpack loader -> SCSS/LESS/Stylus compiler pass -> clean-css pass -> postCSS pass -> write file to disk

Essentially this is analogous to:

text extraction (optional) -> linking -> static analysis -> compiling -> minification -> compatibility sugar -> filesystem IO

linking, static analysis, compiling are through the single libSass pass and are by far the slowest part of the build section. From memory it measures around 55% of build time, with filesystem IO taking another rough 12% which I generally account to be done using Node. Minification of course adds a fair chunk (~32%) which is to be expected, but is quite fast given the size of the CSS being processed (~3mb @ ~900ms).

Ok? What's this got to do with the tool?

Stop CSS rules from conflicting

This is a much larger problem that is endemic of CSS' core design rather than through failings of current solutions to correct it. In the current ecosystem, I've found a lot of people tend to extract CSS from webpack loader output, which often scope the CSS themselves (such as vue-loader's scoped attribute).

I have a couple of ideas about what points would be beneficial to focus on, but my stance is I think it's a problem better reasoned about later in the tool's development:

What CSS properties or features have erroneous behaviour in certain browsers

Tools that correct CSS compatibility issues (usually by implementing CanIUse directly through their DB) are more extensive than pre-processors and already quite fast, and also offer some linting support in the case of PostCSS, but it's plugin ecosystem is a bit NPM messy.

Since this tool is intended to gracefully wrap around a project which may or may not have a large existing pre-processor-styled code-base, I believe there's a couple of specific problems we can solve for CSS to add benefit to the ecosystem:

This means that FEL would be essentially (from a pure-CSS standpoint) able to replace about half of libSass' processing needs, specifically:

Nested CSS

At a high level, I believe what you are talking about is the idea of comparing a sort of abstract syntax tree of CSS specificity and comparing it to an HTML document's structure, flagging any CSS definitions that do not match HTML structure.

If this is the case, a possible solution (or one of) would be to allow developers to define a global CSS source for known global classing that the compiler can assume may slot into any dynamic class rendering. This would also align with the common application design philosophy of a "single source of truth design system", and allow tools down the line to consume these global classes or (possibly) variables.

Framework / Language Agnostic

This brings up the issue that it may be necessary for a plugin system. Fel would say initially support only Moustache Templates and JSX (the post popular I can think of), but allow an API for developers to write their own plugins. This is a Hard Problem, and I don't really have many ideas about how to solve it (I am not as well versed in compilers as I make it sound, and I don't make it sound like I know much).

End Bit

I've rambled a lot here and have created a mess, but it'll be important at these early stages for all people involved in planning - and possibly development - take some time to get onto the same page. Feel free to pick apart my ideas as to whether they suit your vision or not and I'll slowly get a better idea in my head.

silbinarywolf commented 5 years ago

Stop CSS rules from conflicting

We could just leverage the spec/ideas from CSS Modules or CSS Blocks here:

However, we'd like to explore not being too strict on style or having our own special esoteric rules. If we can detect conflicting CSS rules without forcing any specific conventions on users, that might be a nice thing.

Nested CSS

You're correct enough on your first paragraph :) We'd build the HTML tree structures and see what CSS matches in it.

We've already thought about defining global CSS a little bit. There will most likely be a entry point CSS file you define in a project wherein you put any normalization rules, base font formatting and etc.

Framework / Language Agnostic

On this point, I'm not saying the language will support Mustache templates, I'm more saying that it could have its own unique template language that is almost identical to a Mustache template. This would output to other formats like JSX, VueJS templates or Wordpress templates.