cssinjs / jss

JSS is an authoring tool for CSS which uses JavaScript as a host language.
https://cssinjs.org
MIT License
7.06k stars 397 forks source link

[react-jss] Add renderToNodeStream support #807

Open HenriBeck opened 5 years ago

HenriBeck commented 5 years ago

From @rgnevashev on February 26, 2018 17:20

Copied from original issue: cssinjs/react-jss#203

HenriBeck commented 5 years ago

From @kof on February 26, 2018 17:21

I haven't tried yet, feel free to post your findings or work on a PR. This doesn't have high priority for me right now.

HenriBeck commented 5 years ago

From @a-ignatov-parc on February 26, 2018 17:47

Strange, because it should work 🤔

The problem is that you can't send styles before react's stream is completely drained (sent to the client). But that is expected behavior.

app.get('/', (req, res) => {
  const sheets = new SheetsRegistry();

  res.write('<!doctype html><html><head><title>My Page</title></head><body><div id='content'>');

  const stream = renderToNodeStream(
    <JssProvider registry={sheets}>
      <App />
    </JssProvider>
  );

  // `sheets` here are empty
  // sheets.toString(); -> ''

  stream.pipe(res, { end: false });

  stream.on('end', () => {
    // They will be available after app is fully rendered to stream. 
    // The problem is that they are useless here ¯\_(ツ)_/¯
    res.write(`</div><style type="text/css">${sheets.toString()}</style></body></html>`);
    res.end();
  });
});

You can accumulate stream to buffer and wait until styles are available but in this case, renderToNodeStream is mostly useless.

HenriBeck commented 5 years ago

From @kof on February 26, 2018 17:49

I think styles need to be sent before the html they style in order to avoid a FOUC

HenriBeck commented 5 years ago

From @a-ignatov-parc on February 26, 2018 17:49

There is the same problem with any lib that should send its side-effects at the beginning of the page and which result depends on app's render.

HenriBeck commented 5 years ago

From @a-ignatov-parc on February 26, 2018 17:50

I think styles need to be sent before the html they style in order to avoid a FOUC

that is true

HenriBeck commented 5 years ago

From @a-ignatov-parc on February 26, 2018 17:57

I think every css-in-js lib that uses classes is incompatible with renderToNodeStream unless it renders styles right after open tag of the controlled element 🤔

The same problem goes for head-management libs such as react-helmet.

HenriBeck commented 5 years ago

From @kof on February 26, 2018 18:1

I heard SC recently supported it, lets see what they are doing? We could render style tags before each element which needs styles, so that it can be sent right away. I also think this is only possible with react 16, otherwise you would need a wrapping container for each styled component.

HenriBeck commented 5 years ago

From @a-ignatov-parc on February 26, 2018 18:2

I also think this is only possible with react 16

Yes. Also renderToNodeStream is only available in react 16 😉

HenriBeck commented 5 years ago

From @a-ignatov-parc on February 26, 2018 18:9

SC doing chunks reordering which is almost the same as render styles after open tag but requires the use of additional utils.

HenriBeck commented 5 years ago

From @a-ignatov-parc on February 26, 2018 18:11

This could be a good solution for react-jss since there is no styles deduplication.

HenriBeck commented 5 years ago

From @a-ignatov-parc on February 26, 2018 18:12

Only vendor prefixing during ssr could be an issue 🤔

HenriBeck commented 5 years ago

From @kof on June 13, 2018 13:16

https://twitter.com/oleg008/status/1006879080908718081

"It uses a transform stream and when it yields to the transform we get the injected styles up until that point, seal the past server tags, and let it create new ones. Rinse and repeat"

Chunk:
  <style>...</style>
  <component /> 
  <component /> 
  <component /> 
Chunk:
  <style>...</style>
  <component /> 
  <component /> 
  <component />

"Yes and on rehydration we extract out all the style blocks and relocate them to so React doesn’t get mad"

HenriBeck commented 5 years ago

From @kof on June 13, 2018 13:19

We can do it too, exactly the same way. Actually as I wanted to have rehydrate function anyways, this could be added to it https://github.com/cssinjs/jss/issues/677

kelly-tock commented 3 years ago

Will this idea be moving forward?