New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Streaming rendering support #334
Comments
I believe there are other cases where this could fail. Reliance on the cascade is indeed significantly decreased with atomic css, but it is not completely gone. For instance, the following could break until rehydration: // ComponentA.js
import { useStyletron } from "styletron-react";
export default () => {
const [css] = useStyletron();
return (
<div
className={css({
backgroundColor: "#00f",
"@media (min-width: 600px)": {
backgroundColor: "#f00",
},
})}
>
I'm blue and turn red in screens wider than 600px
</div>
);
}; // ComponentB.js
import { useStyletron } from "styletron-react";
export default () => {
const [css] = useStyletron();
return (
<div
className={css({
backgroundColor: "#0f0",
"@media (min-width: 600px)": {
backgroundColor: "#f00",
},
})}
>
I'm green and turn red in screens wider than 600px
</div>
);
}; If because of streaming, server rendered html turns out to be: <style>.a{background-color: "#0f0"}</style>
<style media="(min-width: 600px)">.b{background-color: "#f00"}</style>
<div class="a b">I'm blue and turn red in screens wider than 600px</div>
<!-- ... -->
<style>.c{background-color: "#00f"}</style>
<div class="b c">I'm green and turn red in screens wider than 600px</div> The second div will always remain green, because I'm aware that this can be avoided by using a |
That's a good point! One possible ordering mechanism which I've contemplated in the past is using repeated selectors to enforce precedence regardless of order. For this particular case, all media query styles could simply have a repeated class selector: <style>.a{background-color: #0f0}</style>
<style media="(min-width: 600px)">.b.b{background-color: #f00}</style>
<div class="a b">I'm blue and turn red in screens wider than 600px</div>
<style>.c{background-color: #00f}</style>
<div class="b c">I'm green and turn red in screens wider than 600px</div> This would maintain proper precedence of media query styles and regular styles. However, I think the precedence of media query styles amongst themselves would still be a problem. Prior versions of Styletron didn't make any guarantees about overlapping media queries on the same element (the onus on users to avoid overlapping queries), but it does now. I think ordering the media queries would be difficult using this technique, as you'd need to be able to arbitrarily render styles at specificities between already-rendered styles. Even if you tried to do this, in the worst case, this might be impossible because two selectors may already have adjacent specificities. So I think for progressive rendering, it may be required to have a "strict mode", where warnings are issued for usage of overlapping media queries on the same element and any usage of Then, if there are no warnings, progressive rendering could be safely used without caveats. |
Has anyone made any progress on this sucker? It'd be really awesome to get in, especially as Also, one idea I came across was using inline |
There's similar solution in Glitz. But it renders inline |
@rtsao @TxHawks FYI, this is exactly how Facebook handle their atomic CSS at facebook.com: |
This idea was initially proposed in #137 but I think there's a fairly good way of doing this.
On the server:
<style>
tags from atomic engine<style>
tag stream with the stream returned fromReactDOM.renderToNodeStream
On the client:
ReactDOM.hydrate
, hoist the contents of all the inline<style>
elements into<head>
and remove the inline<style>
elements (while hydrating the cache as normal)I think this would work flawlessly aside from the following (likely exceedingly rare) corner cases where interleaving of streams results in a
<style>
element being inserted:A) as the first child in an element containing children styled with
:first-child
B) as the last child in an element containing children styled with
:last-child
C) into an element containing children styled with
:nth-child
D) between two elements styled with
~
selectorsIf this were to happen, then streaming rendering would cause incorrect styling (at least until the offending inline
<style>
is removed during hydration).The text was updated successfully, but these errors were encountered: