stereobooster / css-in-js-101 Goto Github PK
View Code? Open in Web Editor NEW๐ CSS-in-JS 101: All you need to know
License: MIT License
๐ CSS-in-JS 101: All you need to know
License: MIT License
I try to understand all tradeoffs of different CSS-in-JS approaches. One of the problems is to understand what the setup assumed by the solution and how it affects performance. By "setup" I mean - do we use SSR or Snapshots, do we serve CSS as separate files, do we have critical CSS, do we have async components
(dynamic import
), etc.
To solve the problem, I want to introduce "language" (symbolic representation) which will be able to describe all cases in a dense form. Representation is important, take a look this talk by Bret Victor to understand why.
We have three major "axis" of a web application, they are HTML, CSS, JS. They will be represented by squares with a letter inside:
|J|
- JavaScript|H|
- HTML e.g. Server-Side Rendering or Snapshot|C|
- CSSOn the diagram, they always go in the same order: |J|H|C
.
If "axis" is missing it is represented by an empty box. For example, c-r-a doesn't have SSR out of the box, so there is no prerendered HTML: |J| |C|
---
- "browser" line, everything which is above the line is content loaded in the browser. Everything below the line is not loaded content, for example async components
. Example react-loadable
(or any other async library):
|J| <-- React app
---
|J| <-- async components
~~~
- "browser" line, but loading happens in none-blocking manner. For example loadCSS :
|C|
~~~
Important note: all content of that type should be loaded in the asynchronous mode to be considered as async. So if you have two script tags (with src) in HTML, both should be async
.
One box of the type represents 100% of the required content for the current page to work. If there are two boxes of the same type (above the line), it means there is dead code, which is not needed for the current page. For example, a dead code in CSS in a big library, like bootstrap:
|C|
|C|
---
CSS-in-JS in this dieagram will be represented by CSS square (|C|
) in JS "axis".
|C|
|J|
---
Note: linaria is CSS-in-JS, but will be drawn other way.
Critical CSS inlined in HTML wil be represented by CSS square (|C|
) in HTML "axis".
|C|
|H|
---
Strictly speaking, every React application carries HTML inside, so it should be drawn as HTML square (|H|
) in JS axis, but this will create more noise and confusion, so I prefer to omit it.
So now you know the alphabet.
Let's analyze one setup, so you catch the idea.
Assume we have c-r-a
project with bootstrap, like this one. Let's draw it:
|C| <-- dead code from bootstrap
|J| |C|
-------
^------- no prerendered HTML
What does this tell us? It has pretty poor load performance, there is no HTML, so nothing will be loaded till JS execution. Slow first time to paint. Also slow TTI - everything loaded synchronously.
Let's use react-snap
- a small tool for prerendering SPAs, very useful for small mostly static websites.
|C|
|J|H|C|
-------
This will improve time to first paint. But still we have huge CSS (with dead code) loaded synchronously, let's enable inlineCss
option, which will inline critical CSS and make CSS load async:
|C|C|
|J|H|C|
-----~~
Ah much better - first paint now much faster. HTML and critical CSS are delivered with the first request, so the browser will start to render ASAP. Nice but TTI still can be a problem, there is a JS which is loaded in a synchronous manner. On the other side given website is pretty usable without JS - content is present via prerendered HTML. Filters will not work without JS, but this is not a big issue. So we can use asyncScriptTags: true
|C|C|
|J|H|C|
~~---~~
Now website will be way faster to load.
You need to be aware that this setup does not represent all aspects of a web application. For example:
styled-components
Did I miss something? This diagram doesn't show web fonts for example, which is known performance bottleneck. Comments are welcome.
Related: https://mntr.dk/2014/getting-started-with-assetgraph/
First of all, nice work, it was a great read!
I discuss some of the issues touched in this repository in my library freestyler. Interesting discussion to explore could be the variable scope CSS template has access to. For example, I split those libraries in 1-5th generation.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.