Skip to content
This repository has been archived by the owner on Jun 3, 2019. It is now read-only.

styled-components improvement #297

Open
datoml opened this issue Dec 31, 2016 · 31 comments
Open

styled-components improvement #297

datoml opened this issue Dec 31, 2016 · 31 comments

Comments

@datoml
Copy link
Contributor

datoml commented Dec 31, 2016

Hello,

I made some tests with server side rendering and the styled components feature branch.
Seems like the server side rendering doesn't work for the styles.
Regarding to this discussions styled-components/styled-components#124 I implemented this:

file: src/server/middleware/reactApplication/index.js

import styleSheet from 'styled-components/lib/models/StyleSheet'
...
// Create our React application and render it into a string.
  const reactAppString = renderToString(
    <CodeSplitProvider context={codeSplitContext}>
      <ServerRouter location={request.url} context={reactRouterContext}>
        <DemoApp />
      </ServerRouter>
    </CodeSplitProvider>,
  );

  const styles = styleSheet.rules().map(rule => rule.cssText).join('\n')

  // Generate the html response.
  const html = generateHTML({
    // Provide the full app react element.
    reactAppString,
    // Nonce which allows us to safely declare inline scripts.
    nonce,
    // Running this gets all the helmet properties (e.g. headers/scripts/title etc)
    // that need to be included within our html.  It's based on the rendered app.
    // @see https://github.com/nfl/react-helmet
    helmet: Helmet.rewind(),
    // We provide our code split state so that it can be included within the
    // html, and then the client bundle can use this data to know which chunks/
    // modules need to be rehydrated prior to the application being rendered.
    codeSplitState: codeSplitContext.getState(),
    styledComponents: styles,
  });

Then I added them into

file: src/server/middleware/reactApplication/generateHTML.js
export default function generateHTML(args: Args) {
  const { reactAppString, initialState, nonce, helmet, codeSplitState, styledComponents } = args;
  ...
return `<!DOCTYPE html>
    <html ${helmet ? helmet.htmlAttributes.toString() : ''}>
      <head>
        ${helmet ? helmet.title.toString() : ''}
        ${helmet ? helmet.meta.toString() : ''}
        ${helmet ? helmet.link.toString() : ''}
        ${styleTags(assetsForRender.css)}
        <style>${styledComponents || ''}</style>
        ${helmet ? helmet.style.toString() : ''}
      </head>
      <body>

Looks now a lot nicer to me.
Can someone confirm that this is a good solution? :)
Thanks

@codepunkt
Copy link
Collaborator

It's a start.
More information on styled-components SSR @ styled-components/styled-components#214

@ctrlplusb
Copy link
Owner

Thanks for looking into this @datoml :)

I'll have a review of this soon. :)

@teonik
Copy link

teonik commented Jan 9, 2017

The glamor styleSheet that styled-components exposes is a singleton.With the above approach every request to render a page will result in it's styles being appended to it.So in subsequent requests you end up sending previously rendered CSS unrelated to the current page.

Calling styleSheet.flush() in between requests doesn't seem to work at the moment.

@ctrlplusb
Copy link
Owner

Has someone got a full working implementation that they are willing to create a PR for?

@datoml
Copy link
Contributor Author

datoml commented Jan 9, 2017

I am currently using styled-components for my project with the hope that there will be a fix in die near future for this.
@ctrlplusb I am not that familiar with creating a PRs :).

@ctrlplusb
Copy link
Owner

@datoml I encourage you to try!

Check out this cool egghead course:
How to Contribute to an Open Source Project on GitHub

@datoml
Copy link
Contributor Author

datoml commented Jan 9, 2017

Thanks for the link. I'll have a look :):

@rlindskog
Copy link
Contributor

@ctrlplusb I implemented the SSR changed that @datoml recommended above, you can check it out here. It seems to work, but it double injects the styles, once on the server and once on the client.

@codepunkt
Copy link
Collaborator

I'm wondering if you read what i linked. That's all known and discussed and there's no solution for it yet, even though it's very simple in principle
styled-components/styled-components#214

@datoml
Copy link
Contributor Author

datoml commented Jan 10, 2017

I did.
We currently have to wait that this gets implemented.
Everything here is currently a workaround until its done and gets released.

@ctrlplusb
Copy link
Owner

FYI I have been using styletron, which has no problems with SSR and has a similar API to styled-components. In case this is blocking someones adoption, there are alternatives.

@datoml
Copy link
Contributor Author

datoml commented Jan 10, 2017

I tried styletron but I like the api from styled-components more.
Doing something like this feels awesome to me :).

import styled from 'styled-components';

const button = styled.button`
  color: green;
  border: 1px solid blue;
`;

@codepunkt
Copy link
Collaborator

codepunkt commented Jan 10, 2017

I'm hard to convince as well. On the one hand i'm not sure about the performance implications of styletrons many CSS selectors in really large DOMs (think Githubs Diff view), on the other hand i love to be able to write CSS instead of objects, including inline syntax highlighting etc, so i'm with @datoml on that one :)

@ctrlplusb
Copy link
Owner

Totally see your guys points, I guess I prefer the object style as it opens up the Javascript as the API to modifying/merging styles:

const centeredButtonStyle = Object.assign(
  {}, 
  { color: 'red' },
  theme.layout.centered
); 

I have been really enjoying creating and composing objects for more generic styles.

@datoml
Copy link
Contributor Author

datoml commented Jan 10, 2017

Thats true.
The reason styled-components won my heart was that I can copy the whole css and go back to good old css styles.
Every approach has it pros and cons tho :).

@ctrlplusb
Copy link
Owner

Check this out: https://github.com/RafalFilipek/styled-props

:)

@datoml
Copy link
Contributor Author

datoml commented Jan 11, 2017

I will have a look on it :).
But it seems similar to the build in ThemeProvider.
https://github.com/styled-components/styled-components#theming

Or am I missing something? :D

@teonik
Copy link

teonik commented Jan 11, 2017

@codepunkt Thanks for suggesting styletron, i was totally unaware of it's existence....:P

@lucianlature
Copy link
Collaborator

@ctrlplusb @codepunkt Server Rendering API for styled-components has just been merged into master

@codepunkt
Copy link
Collaborator

@lucianlature it was merged into v2 branch, not master.

@lucianlature
Copy link
Collaborator

Got too excited for a moment, sorry.

@bkniffler
Copy link
Collaborator

Out of curiosity, did you guys look at https://github.com/rofrischmann/fela
According to https://github.com/hellofresh/css-in-js-perf-tests it is extremely fast and creates very small sized output compared to something like glamor/styletron. The docs are great (http://fela.js.org/docs/guides/UsageWithReact.html), it works with react-native, and SSR is implemented and works too.

And with https://github.com/jakecoxon/babel-plugin-css-to-js you can have a very similar API to styled-components!

@codepunkt
Copy link
Collaborator

@bkniffler The alternatives are endless. CSS in JSS fatigue! 🤣

@mschipperheyn
Copy link

In order to get styled-components working server-side with current v2-beta, which api seems still a bit under discussion (styled-components/styled-components#214), you can use this approach.

https://gist.github.com/mschipperheyn/c17280278218074a53147f54259af66a

The reference keyword is: styledComponentCSS

I based this on react-universally@next

@designspin
Copy link

Does anybody have styled components working with react universally nowadays? I am using version 2.1.1 of styled components, but have not had any joy. I looked at the gist provided by 'mschipperheyn', but it looks like things have changed in styled-components land!

I am trying to use ServerStyleSheet, creating an instance and then using collectStyles on my app component. But I am missing something, getStyleElement returns an empty array. I know that app is async so perhaps at the point of collection it is empty?

@designspin
Copy link

Okay, I was on the right track. I managed to implement Styled Components by passing my ServerStyleSheet instance as a prop on ServerHTML, then using .getStyleElement() to add the css to headerElements within ServerHTML.js. I am really pleased I got this working and also pleased I found React Universally.

@oyeanuj
Copy link
Contributor

oyeanuj commented Jul 13, 2017

@designspin is there a gist you could share if it all works? Btw, here is the main issue on styled-components where you could also maybe post that update for others following the issue - styled-components/styled-components#762

@designspin
Copy link

designspin commented Jul 13, 2017

@oyeanuj

Here is a GIST of what appears to be working for me right now: https://gist.github.com/designspin/c11095334ae1f105d1f93123232d37fd

@strues
Copy link
Collaborator

strues commented Jul 13, 2017

@designspin If you will link me a repo where you're having issues, I'll take a look.

@designspin
Copy link

@strues

No issue, the above GIST is in fact a solution. It is working for me, thanks.

@oyeanuj
Copy link
Contributor

oyeanuj commented Aug 31, 2017

@mschipperheyn @strues @designspin Does anyone have the setup for using the starter kit with SC v2? The feature branch still seems to have v1 of SC.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests