-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Server Side Rendering #124
Comments
I'll gladly help test this out! We currently avoid using styled components for most styles because of the unclear path to support SSR, would be great to move the inline styles into styled components if we can generate the CSS on the server. Here is what I have setup so far: import styleSheet from 'styled-components/lib/models/StyleSheet';
styleSheet.flush();
let markup = renderToString(
<Root store={store} Router={ServerRouter} routerProps={{ location, context }} />
);
console.log(styleSheet.rules()); Unfortunately, I'm getting back an empty array |
I'm currently implementing SSR on a project and I managed to make this work without Once I finish it I will post the complete code and a demo here. (I'm trying to make the app work completely without javascript enabled on client). |
Huh, that's interesting. I think I might accidentally use another |
Demo: https://arc.diegohaz.com (disable javascript, even the form works). It doesn't work with The |
I noticed something. code is like this:
Invoked as css gets rendered as
The element receives the correct classname on SSR (class="iMsaJZ hqknNf"), wich are two classes, one for my code(iMsaJZ) and one for Grid's(hqknNf).
Inlining code solves the problem and ssr can be used but it breaks composition :( Also to notice that while profiling on my dev pc (windows 10) I got 0 ~ 1ms latency calling styleSheet.rules().map(rule => rule.cssText).join('\n') |
Based on @pheuter test, I get the same result,(the class is injected in the string markup) but not calling |
Ah, this is so great. I was able to get it working with gatsby in no time render () {
const styles = styleSheet.rules().map(rule => rule.cssText).join('\n');
return (
<html lang="en">
<head>
<style>
{styles}
</style>
</head>
<body>
<div id="react-mount" dangerouslySetInnerHTML={{ __html: this.props.body }} />
<script src={prefixLink(`/bundle.js?t=${BUILD_TIME}`)} />
</body>
</html>
)
} I'm all for exposing a simpler api via |
@gbozee I ran into that problem. Turns out when (f.e.) webpack 2 is used, it loads the es bundle, due to the Until there is an API for the stylesheet that we can use, you should work around it using webpack's |
…box. Now if you use [Glamor](https://github.com/threepointone/glamor/) to write your style, static rendering will take that into account and will prerender styles for you. Nothing to setup. It’s even injecting glamor ids if you want to rehydrate on startup. See [glamor server documentation](https://github.com/threepointone/glamor/blob/master/docs/ server.md) to setup hydratation (you will need to handle this yourself in your ``scripts/phenomic.browser.js``. Since [styled-components](https://styled-components.com/) [use Glamor under the hood](styled-components/styled-components#124) , this will work for this library as well. Ref #864
…box. Now if you use [Glamor](https://github.com/threepointone/glamor/) to write your style, static rendering will take that into account and will prerender styles for you. Nothing to setup. It’s even injecting glamor ids if you want to rehydrate on startup. See [glamor server documentation](https://github.com/threepointone/glamor/blob/master/docs/ server.md) to setup hydratation (you will need to handle this yourself in your ``scripts/phenomic.browser.js``. Since [styled-components](https://styled-components.com/) [use Glamor under the hood](styled-components/styled-components#124) , this will work for this library as well. Ref #864
@mxstbr I'm interested in solving this ( |
Please get in touch when somebody start to handle this. I would like to get this to work out of the box in Phenomic (I just integrated Glamor and Aphrodite rendering and would like to cover all populars CSS in JS solutions). |
@aesopwolf did you get the same problem as @diegohaz of not having styles included from injectGlobal calls? I think its a general consensus that this is working out of the box. The only minor caveat is styles from injectGlobal isn't included. But fixing that is trivial I guess? |
We will wait for official API styled-components/styled-components#124
@thisguychris I just ran a quick test with Input: const Title = styled.h1`
font-size: 1.5em;
text-align: center;
color: palevioletred;
`;
injectGlobal`
body {
background: red;
}
`; Output: <style>
.kZQsGZ {
font-size: 1.5em;
text-align: center;
color: palevioletred;
}
body {
background: red;
}
</style> |
Yeah the implementation for |
@geelen so do we get a green light for the exposed api? aka serverStylesheet.getCSS()? Also, @aesopwolf would you mind giving me a test repo of your SSR to test my PR with? |
I would love an exposed API, would love for you to look into that @thisguychris! |
You guys are right, Sorry for the mess. |
Now this repo is working with @thisguychris |
It would be great if this.sheet = {
cssRules: [],
insertRule: rule => {
const serverRule = { cssText: rule }
this.sheet.cssRules.push(serverRule)
return {serverRule, appendRule: (newCss => serverRule.cssText += newCss)}
}
}
this.sheet.cssRules = [] So after flushing EDIT: |
- fixes styled-components#124 - remap flush to reset() - convenience function getCSS() for SSR
- reference issue styled-components#124 and the PR itself
I am trying to use hedron, but it seems the styles from it are not present. But my custom styles are rendered fine. Any ideas why this is happening/how to work around? |
- fixes styled-components#124 - remap flush to reset() - convenience function getCSS() for SSR update CHANGELOG.md - reference issue styled-components#124 and the PR itself removed prototype changed to ServerStyleSheet as Pascal Case - as per [@diegohaz](https://github.com/diegohaz) recommendation remove mutation and capitlization in export renamed serverStyle to styleSheet and refactor - now just extending StyleSheet as pointed out by geeleen - renamed flush as reset - added convenience function to call rules.map...
@jorilallo I had quite similar issue. In my case I solved it by adding 'styled-components/lib/models/StyleSheet' in externals in webpack 2.
it was not there because I was adding only the node_modules root folder to externals. |
I'm not sure why this is so hard using @geelen Concatenating the resulting cssText is fine, but it should also be rehydrated on server-side to prevent the client from injecting the styles again. |
@code-punkt see #214 :) |
@aesopwolf thanks for the code snippet, worked with Gatsby for me too. But I think it should be |
@tomazy You can always remove your SSR style block once the client-side rendering is done. That way, your page will look great while the app is loading and you will not get duplicate styles. ReactDOM.render(<App />, document.getElementById('app'));
document.getElementById('ssr-style').remove(); |
@tomazy I used something similar to remove the server rendered critical-css block when react and styled-components kicked in on the client side. Of course there are simpler ways to stick some global css in the pre-rendered page's |
- fixes styled-components#124 - remap flush to reset() - convenience function getCSS() for SSR update CHANGELOG.md - reference issue styled-components#124 and the PR itself removed prototype changed to ServerStyleSheet as Pascal Case - as per [@diegohaz](https://github.com/diegohaz) recommendation remove mutation and capitlization in export renamed serverStyle to styleSheet and refactor - now just extending StyleSheet as pointed out by geeleen - renamed flush as reset - added convenience function to call rules.map...
PSA: I was seeing
The fix: If you are seeing this as well, make sure you are rendering at least one styled component in your app. For me, I was just installing |
I have submitted a PR to fix this issue here. Hope this helps some! |
@dignifiedquire - Could you please tell me how you worked around this? I'm having the exact same issue with hedron. |
@karthikiyengar Hedron is using styled-components which I believe means you need to import both your own server markup and theirs. |
@kristojorg - Thanks for your answer. Please disregard, my vendor assets weren't being generated properly, leading to the issue. |
This discussion has now been moved to #386. |
…box. Now if you use [Glamor](https://github.com/threepointone/glamor/) to write your style, static rendering will take that into account and will prerender styles for you. Nothing to setup. It’s even injecting glamor ids if you want to rehydrate on startup. See [glamor server documentation](https://github.com/threepointone/glamor/blob/master/docs/ server.md) to setup hydratation (you will need to handle this yourself in your ``scripts/phenomic.browser.js``. Since [styled-components](https://styled-components.com/) [use Glamor under the hood](styled-components/styled-components#124) , this will work for this library as well. Ref #864
We will wait for official API styled-components/styled-components#124
Thought I'd open an issue to kick off the discussion. It's already possible because of the way we build on top of Glamor, but we haven't exposed it as an API. But basically, if you did this:
Then you should get the chunk of CSS you need for each request. Can someone with a server-rendered setup take a look and confirm this works, and maybe show how they'd be invoking it? I'd be happy enough to export something like:
What do people think?
The text was updated successfully, but these errors were encountered: