Open kripod opened 4 years ago
As suggested by @amannn, styling rules with discrete values may also be extracted statically, e.g.:
css({ flexDirection: reverse ? "column-reverse" : "column" })
Could be decomposed into two CSS rules and then transformed into:
reverse ? "staticClassName1" : "staticClassName2"
For future reference, CSS custom properties and data attributes should make the extraction of dynamic rules possible.
Q: how do you deal with things like this?
const rest = { flexGrow: 0 }
;<div css={{ flex: 1, ...rest }}/>
Q: how do you deal with things like this?
const rest = { flexGrow: 0 }; <div css={{ flex: 1, ...rest }}/>
That’s an interesting edge-case, thank you! I’m not sure about the limits of static analysis, but if the value of rest
can be resolved in the context (it isn’t a function parameter), then its static and dynamic blocks may be taken apart.
The rest
variable shall be left intact. A minifier could eliminate it if not used elsewhere.
Example output:
const rest = { flexGrow: 0 };
const restStatic = "hashedClassName"; // css({ flexGrow: 0 })
const restDynamic = css({ /* … */ }); // Not required here
<div className={`flex1ClassName ${restStatic} ${restDynamic}`} />
Motivation
As of today, popular runtime CSS-in-JS libraries like Emotion and Styled Components all emit static styles into JavaScript bundles. By this regard, otion is no exception, as seen in the resulting bundle generated by Next.js on the right:
Basic example
The styling code shown on the previous image is as follows:
It can be split into two parts, possibly with a Babel plugin:
css({ display: "flex" })
css
function call.The static part may be replaced with its corresponding hashed class name string ahead of time.
Details
While replacing constant-parametered calls to
css
andkeyframes
works with server-side rendering and inlined<style>
tags, some styles may become missing once client-side navigation happens.To make the solution router-compatible, static styles of the entire website should be collected and then emitted into a single static CSS file (e.g. with webpack), possibly with file name hashing and infinite caching in place. By referring to the result through a
<link>
, every static styling rule gets loaded in the background, so routing can happen without missing any styles.When opting for ahead of time static rule processing,
filterOutUnusedRules
should not be used, as state changes may result in referring to class names filtered out during SSR.In conclusion, style loading should happen like:
<style>
tag for no round trips over HTTP 1.<link>
stay intact. No inlined styles should be loaded on client-side route changes, as all the static CSS should be available by the time a navigation happens.