Skip to content
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

styled-component overridden on hot reload #4068

Closed
ghost opened this issue Mar 28, 2018 · 33 comments
Closed

styled-component overridden on hot reload #4068

ghost opened this issue Mar 28, 2018 · 33 comments
Labels
good first issue Easy to fix issues, good for newcomers

Comments

@ghost
Copy link

ghost commented Mar 28, 2018

  • [x ] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

My page contains this very basic code:

import React from 'react'
import styled from 'styled-components'

const Title = styled.h1`
  color: pink;
  font-size: 50px;
`

export default () => <Title>My page</Title>

When I refresh the page, I expect the Title to be of color pink

Current Behavior

The first time the page is built, the title does appear as pink. When I refresh the page, the pink color is no longer respected.
If I change the color in the code to anything else, and save the file, then the page will update. But again, upon refreshing, the changes are lost again. I have no clue what might be causing this. Any help is appreciated.

Your Environment

Tech Version
next latest
node
OS arch
browser vivaldi
@lucleray
Copy link
Member

lucleray commented Apr 3, 2018

I have the same bug, with a different setup. I have a monorepo with two folders :

  • app, with my next.js app
  • ui , with my 'ui library' using styled-components

I have it in an example repo : https://github.com/lucleray/ssr-ui-library

When I update the background color for example, in the ui folder, and save the file, the page updates.
But then, if I refresh the page, the updates are lost.

@ianregister
Copy link

Is this anything to do with the injection order of the style sheets in <head>?

@lucleray
Copy link
Member

lucleray commented Apr 8, 2018

@ianregister No, the order of the injection in <head> is not related

The problem is that the server and the client don't render the same code for stylesheets

@sea129
Copy link

sea129 commented Apr 17, 2018

I have the same bug and it is not only on styles. Hot reload will pick up the changes, but refreshing browser does not. I have to run server again (node server.js) in order to pick up the latest update. I am using next@6.0-canary.3, react 16.3 and express for the server.

@tvthatsme
Copy link
Contributor

@lucleray, try this:

Make sure you have babel-plugin-styled-components as a dependency and in your package.json tell babel that you are doing server-side rendering.

Think that this is just a configuration issue you are facing.

package.json

"babel": {
    "env": {
      "development": {
        "presets": ["next/babel"],
        "plugins": [
          [
            "styled-components",
            {
              "ssr": true,
              "displayName": true
            }
          ]
        ]
      },
      "production": {
        "presets": ["next/babel"],
        "plugins": [
          [
            "styled-components",
            {
              "ssr": true,
              "displayName": false
            }
          ]
        ]
      }
    }
  }

@lucleray
Copy link
Member

@tvthatsme I added babel-plugin-styled-components in both the ui library and the app itself, but I still have the same issue.

You can check here :
https://github.com/lucleray/ssr-ui-library/blob/master/app/.babelrc
https://github.com/lucleray/ssr-ui-library/blob/master/ui/.babelrc

I'm not sure it is configuration (webpack configuration), or a bug somewhere.

@timneutkens timneutkens added help wanted good first issue Easy to fix issues, good for newcomers labels May 29, 2018
@valeeum
Copy link

valeeum commented Jul 25, 2018

having similar issue where any edits to a component (non styles related) will cause an error "Warning: Prop className did not match. Server:" on subsequent hard page fresh. Need to restart server for it to go away.

@sea129 were you able to fix?

@chenshuiluke
Copy link

Lol, having the same issue here. @valeeum were you able to solve it?

@lucleray
Copy link
Member

lucleray commented Aug 19, 2018

I did a bit of research on this issue, and I think it might be link some sort of "webpack caching".

I use the code here as an example of the issue : https://github.com/lucleray/ssr-ui-library

The app is using Next.js and has a dependency on the ui. I'm using yarn's workspace to link them but it could be a more simple yarn link.

On the server-side, the bundle does not include the ui module and treats it as external (because it's in node_modules).
On the client-side, the bundle includes the ui module.

It appears like this in the .next/static (client-side) bundles :

/***/ "../ui/bundle.js":
/*!***********************!*\
  !*** ../ui/bundle.js ***!
  \***********************/
/*! no static exports found */
/***/ (function(module, exports, __webpack_require__) {

"use strict";


Object.defineProperty(exports, '__esModule', { value: true });

function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }

var styled = _interopDefault(__webpack_require__(/*! styled-components */ "../node_modules/styled-components/dist/styled-components.browser.esm.js"));

const UiButton = styled.button`
  background: black;
`;

exports.UiButton = UiButton;


/***/ }),

On the other hand, in the .next/server (server-side) bundles, it appears like this :

/***/ "@monorepo/ui":
/*!*******************************!*\
  !*** external "@monorepo/ui" ***!
  \*******************************/
/*! no static exports found */
/***/ (function(module, exports) {

module.exports = require("@monorepo/ui");

/***/ }),

What is weird is that module.exports = require("@monorepo/ui") should resolve to the ui package and just work fine. But it seems like it's cached and does not resolve to the actual ui package.

If I change the background color of the button in the ui to blue for example. The hot reloader updates the page correctly. But if I refresh, then the page is rendered server-side with the old color (green in my example). It's like the server-side bundle is not resolving the @monorepo/ui dependency to go the actual package, but is using a cached version of it.


It solved it by configuring webpack to treat @monorepo/ui not as an external dependency and bundle it in the server-side bundles, like this : https://github.com/lucleray/ssr-ui-library/blob/webpack-config/app/next.config.js

I would still like to understand what's happening 🤔

@timneutkens
Copy link
Member

require has a built-in cache (require.cache) this is expected behavior for dependencies in node_modules, as we won't bundle anything inside node_modules on the server (for compilation speed).

@lucleray
Copy link
Member

Ok, that makes sense.

So the issue is that the hot-reloader doesn't reload the code changes in external dependencies, on the server-side, right ?

In the example I shared, I expect my code changes to be loaded both on client (which is the case) and server (which is not the case) side in development mode.

@timneutkens
Copy link
Member

So the issue is that the hot-reloader doesn't reload the code changes in external dependencies, on the server-side, right?

Exactly, we only delete full paths from the require.cache.

@lucleray
Copy link
Member

How do you think I could solve this @timneutkens ?

Should I remove @monorepo/ui from the external dependencies so it's bundled in the server-side bundles ? That works but since I'm already transpiling it, wouldn't it better to just require it ?

@timneutkens
Copy link
Member

It might be as easy as using https://github.com/martpie/next-plugin-transpile-modules to enable module compilation.

@jeankvd
Copy link

jeankvd commented Mar 15, 2019

@timneutkens Why was this closed? this issue still exists on the latest version

@oscargws
Copy link

oscargws commented Apr 6, 2019

Still having this issue as well

@asotoglez
Copy link
Contributor

Im still having this issue too

@Ruegen
Copy link

Ruegen commented Apr 14, 2019

Ditto too here

@MadMaxMcKinney
Copy link

MadMaxMcKinney commented Apr 19, 2019

Also having this issue

Edit (solution):

This issue is related to not having the babel config setup correctly. If you look at the official example of NextJS with styled-components you'll notice they have a .babelrc file with:

{
    "presets": ["next/babel"],
    "plugins": [["styled-components", { "ssr": true }]]
}

Then you must add this plugin to the devDependencies in your package.json file

"devDependencies": {
    "babel-plugin-styled-components": "^1.8.0"
},

Then run your install command, yarn install or npm install and then you'll be good to go!

P.S: Be sure to only have one tab open for your localhost dev work!

@ghost
Copy link

ghost commented Sep 4, 2019

ok people. here is the solution. create an _document.js in root of directory and add this.

import Document, { Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'

class MyDocument extends Document {
  static getInitialProps ({ renderPage }) {
    const sheet = new ServerStyleSheet()
    const page = renderPage(App => props => sheet.collectStyles(<App {...props} />))
    const styleTags = sheet.getStyleElement()
    return { ...page, styleTags }
  }

  render () {
    return (
      <html>
        <Head>
          <title>Your site title</title>
          {this.props.styleTags}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </html>
    )
  }
}

export default MyDocument

then npm install --save -D babel-plugin-styled-components

also create a custom app in pages directory, _App.js and add:

import React from "react";
import App from "next/app";

class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props;
    return <Component {...pageProps} />;
  }
}

export default MyApp;

you're all set

@omendez85
Copy link

Also having this issue

Edit (solution):

This issue is related to not having the babel config setup correctly. If you look at the official example of NextJS with styled-components you'll notice they have a .babelrc file with:

{
    "presets": ["next/babel"],
    "plugins": [["styled-components", { "ssr": true }]]
}

Then you must add this plugin to the devDependencies in your package.json file

"devDependencies": {
    "babel-plugin-styled-components": "^1.8.0"
},

Then run your install command, yarn install or npm install and then you'll be good to go!

P.S: Be sure to only have one tab open for your localhost dev work!

This works, Thanks

@TheRusskiy
Copy link
Contributor

TheRusskiy commented Nov 21, 2019

Unfortunately, it's still an issue.

I am witnessing something weird though:

If you have

styled.h1`
color: red;
`

on the initial load it's red, when you change it to

styled.h1`
color: purple;
`

it gets ignored, text becomes black, no styles.
When you reload the page it gets purple as expected.
But when you then change color to red, HMR works properly and text becomes red.
You can do it with as many colors if you want, like if some kind of caching going on.

So when you add a new style via HMR it gets ignored, but on initial render it's placed in cache, and if you use this style later via HMR it's gonna work. So it's not delivered to browser properly on HMR?

I don't have knowledge on SC and Next.js internals, so those are just my guesses.

EDIT:
it worked ok on styled-components 5.0.0-rc.2

@Igor2122
Copy link

not sure how relevant this info will be, but how i fixed it for myself is i followed the example from next repo and integrated the missing bits a pieces
https://github.com/zeit/next.js/tree/canary/examples/with-typescript-styled-components

@gavinmcfarland
Copy link

I was using next.js and @maxmckinney solution worked for me. Just make sure you have configured the .babelrc preferences correctly as it's quite a confusing format or arrays and objects to follow.

This was my .babelrc file for example:

{
    "presets": [
        [
            "next/babel",
            {
                "styled-jsx": {
                    "plugins": [
                        "styled-jsx-plugin-postcss"
                    ]
                }
            }
        ]
    ],
    "plugins": [
        [
            "styled-components",
            {
                "ssr": true
            }
        ]
    ]
}

@CalvinKorver
Copy link

This issue will occur if you're cloning and building on one of the Next.js examples that don't have the same package.json dependencies and .babelrc settings. In addition to MaxMckinney solution, ensure that you have the correct dependency in package.json. I was outright missing "styled-components": "^5.0.0"

@taiwanhua
Copy link

taiwanhua commented Jul 23, 2020

In my case ,just add _app.js and _document.js file under pages floder,it work fine.

// _app.js
import App from 'next/app'
import { ThemeProvider } from 'styled-components'

const theme = {}

export default class MyApp extends App {
    render() {
        const { Component, pageProps } = this.props
        return (
            <ThemeProvider theme={theme}>
                <Component {...pageProps} />
            </ThemeProvider>
        )
    }
}
// _document.js
import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        })

      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      }
    } finally {
      sheet.seal()
    }
  }
}

@521707
Copy link

521707 commented Aug 24, 2020

In my case ,just add _app.js and _document.js file under pages floder,it work fine.

// _app.js
import App from 'next/app'
import { ThemeProvider } from 'styled-components'

const theme = {}

export default class MyApp extends App {
    render() {
        const { Component, pageProps } = this.props
        return (
            <ThemeProvider theme={theme}>
                <Component {...pageProps} />
            </ThemeProvider>
        )
    }
}
// _document.js
import Document from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        })

      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      }
    } finally {
      sheet.seal()
    }
  }
}

How should I use it in the Material-UI?

@SPeshov
Copy link

SPeshov commented Jan 21, 2021

I had only one component failing and after trying everything from the above examples only this helped:
Screenshot 2021-01-21 at 14 09 46

It was picking up styles from some other div component, so I've tried adding id on them hoping that it will resolve somehow but it did no.

The only thing that worked was switching from div to some other element type.

@ConstaXI
Copy link

@lucleray, try this:

Make sure you have babel-plugin-styled-components as a dependency and in your package.json tell babel that you are doing server-side rendering.

Think that this is just a configuration issue you are facing.

package.json

"babel": {
    "env": {
      "development": {
        "presets": ["next/babel"],
        "plugins": [
          [
            "styled-components",
            {
              "ssr": true,
              "displayName": true
            }
          ]
        ]
      },
      "production": {
        "presets": ["next/babel"],
        "plugins": [
          [
            "styled-components",
            {
              "ssr": true,
              "displayName": false
            }
          ]
        ]
      }
    }
  }

Thanks, it worked here!

@brianwachira
Copy link

Also having this issue

Edit (solution):

This issue is related to not having the babel config setup correctly. If you look at the official example of NextJS with styled-components you'll notice they have a .babelrc file with:

{
    "presets": ["next/babel"],
    "plugins": [["styled-components", { "ssr": true }]]
}

Then you must add this plugin to the devDependencies in your package.json file

"devDependencies": {
    "babel-plugin-styled-components": "^1.8.0"
},

Then run your install command, yarn install or npm install and then you'll be good to go!

P.S: Be sure to only have one tab open for your localhost dev work!

For ones going through the same issue, this worked for me.
I also got help from this article

@mateenkiani
Copy link

mateenkiani commented Sep 1, 2021

I was having the exact same issue and it was resolved by doing:

npm i babel-preset-next
npm install --save -D babel-plugin-styled-components

and adding this to .babelrc file:

{
    "presets": ["next/babel"],
    "plugins": [["styled-components", { "ssr": true }]]
}

@N3XT14
Copy link

N3XT14 commented Dec 25, 2021

I am not using babel but SWC hence I don't have the .rc file. Since the issue is still present. Can anyone suggest what configuration will be needed and where to fix this issue?

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 27, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
good first issue Easy to fix issues, good for newcomers
Projects
None yet
Development

No branches or pull requests