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

FOUC: Warning: Text content did not match. Server: "...css..." #3108

Closed
1 task done
lancejpollard opened this issue Oct 16, 2017 · 25 comments
Closed
1 task done

FOUC: Warning: Text content did not match. Server: "...css..." #3108

lancejpollard opened this issue Oct 16, 2017 · 25 comments

Comments

@lancejpollard
Copy link

lancejpollard commented Oct 16, 2017

Getting large error (printing all of CSS used in <style jsx global>) in web console.

Warning: Text content did not match. Server: "
...(css)...

I think this is causing FOUC, so there is a flash of unstyled content followed by a second later the actual styles.

This is coming from a library being used in a next project (from #3088).

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

Expected Behavior

  • Styles should be applied from server directly.
  • There should be no FOUC
  • There should be no error in web console

Current Behavior

To elaborate a little more, when rendering a next app in the library itself (so some page in that repo), the styles render fine. View-source shows source maps and minified CSS in the HTML markup.

However, when using that same code as a compiled project loaded into a separate next app, the markup in view-source shows unminified CSS and no source maps (and we get the web console error and fouc).

Steps to Reproduce (for bugs)

  1. See ModuleParseError when referencing external repo #3088 for setup.
  2. I am manually compiling some files in repo-b using babel <folder> --out-dir ... etc., and then importing that and also importing babel-polyfill if that matters.

Context

This is just unexpected behavior making the app not look right (ux).

Your Environment

Tech Version
next 4beta2
node 8.4
@lancejpollard
Copy link
Author

Hmm what could be happening as a rough guess is because it's being precompiled with babel and babel-polyfill is being used, its not getting passed through the styled-jsx when its being rendered on the server for some reason. Not sure.

@e10jon
Copy link

e10jon commented Oct 16, 2017

I'm getting this as well. I believe it has to do with the CSS being encoded when rendered. Here's the full warning message I receive:

warning.js?dce5fb5:33 Warning: Text content did not match. Server: "
      html, body, body &gt; div, #__next, #__next &gt; div { height: 100% }
      main {
        margin-bottom: -100px;
        min-height: 100%;
      }
      main:after {
        content: &quot;&quot;;
        display: block;
        height: 100px;
      }
      footer {
        height: 100px;
      }
    " Client: "
      html, body, body > div, #__next, #__next > div { height: 100% }
      main {
        margin-bottom: -100px;
        min-height: 100%;
      }
      main:after {
        content: "";
        display: block;
        height: 100px;
      }
      footer {
        height: 100px;
      }
    "

@lancejpollard
Copy link
Author

Also getting stuff like this, which seems related:

Warning: Received `true` for non-boolean attribute `jsx`. If this is expected, cast the value to a string.
    in style
    in div
    in Layout (at index.js?entry:13)
    in HomePage
    in AppContainer
    in Container
    in div
    in App

If it has <style jsx>, not sure why this message would be occurring.

@lancejpollard
Copy link
Author

I tried reproducing it but in the simple case it seems fine.

@lancejpollard
Copy link
Author

lancejpollard commented Oct 17, 2017

@e10jc nice I see what you mean. It looks like its the encoding of those quotes and probably other stuff. Simple case:

Text content did not match. Server: "
body {
  background: red
}

body:before {
  content: &#x27;&#x27;;
}
  " Client: "
body {
  background: red
}

body:before {
  content: '';
}

But that itself isn't causing the FOUC. Still not sure about that.

@lancejpollard
Copy link
Author

lancejpollard commented Oct 17, 2017

Looking at the HTML elements debugger in Chrome, there is a ~1s delay to add the title tags (and anything following that in the head perhaps?):

<head>
<link rel="preload" href="/_next/1508208268137/page/" as="script">
<link rel="preload" href="/_next/1508208268137/page/_error/index.js" as="script">
<link rel="preload" href="/_next/1508208268137/manifest.js" as="script">
<link rel="preload" href="/_next/1508208268137/commons.js" as="script">
<link rel="preload" href="/_next/1508208268137/main.js" as="script">
<meta charset="utf-8" class="next-head">
<title>Home page</title>
</head>

The title appears a few frames afterward. Maybe its related to that.

@lancejpollard
Copy link
Author

lancejpollard commented Oct 17, 2017

YAY It is the encoding! Here is an example to see it:

body {
  font-family: "Helvetica Neue";
}

The quotes get mangled and so it will be Times New Roman or whatever before the client-side styles are applied.

View-source looks like this:

  | <!DOCTYPE html><html><head><link rel="preload" href="/_next/1508208791129/page/" as="script"/><link rel="preload" href="/_next/1508208791129/page/_error/index.js" as="script"/><link rel="preload" href="/_next/1508208791129/manifest.js" as="script"/><link rel="preload" href="/_next/1508208791129/commons.js" as="script"/><link rel="preload" href="/_next/1508208791129/main.js" as="script"/><meta charSet="utf-8" class="next-head"/></head><body><div><div id="__next"><div data-reactroot=""><div class="jsx-1522239983"><style>
-- | --
  | :root {
  | --default-color: red;
  | }
  | </style><style>
  | body {
  | --default-font: &quot;Helvetica Neue&quot;;
  | background: var(--default-color);
  | font-family: var(--default-font);
  | }
  |  
  | body:before {
  | content: &#x27;&#x27;;
  | }
  | </style>Hello World</div></div></div><div id="__next-error"></div></div><div><script>
  | __NEXT_DATA__ = {"props":{},"pathname":"/","query":{},"buildId":1508208791129,"buildStats":null,"assetPrefix":"","nextExport":false,"err":null,"chunks":[]}
  | module={}
  | __NEXT_LOADED_PAGES__ = []
  | __NEXT_LOADED_CHUNKS__ = []
  |  
  | __NEXT_REGISTER_PAGE = function (route, fn) {
  | __NEXT_LOADED_PAGES__.push({ route: route, fn: fn })
  | }
  |  
  | __NEXT_REGISTER_CHUNK = function (chunkName, fn) {
  | __NEXT_LOADED_CHUNKS__.push({ chunkName: chunkName, fn: fn })
  | }
  | </script><script async="" id="__NEXT_PAGE__/" type="text/javascript" src="/_next/1508208791129/page/"></script><script async="" id="__NEXT_PAGE__/_error" type="text/javascript" src="/_next/1508208791129/page/_error/index.js"></script><div></div><script type="text/javascript" src="/_next/1508208791129/manifest.js"></script><script type="text/javascript" src="/_next/1508208791129/commons.js"></script><script type="text/javascript" src="/_next/1508208791129/main.js"></script></div></body></html>
--default-font: &quot;Helvetica Neue&quot;;

Seems like that doesn't work in the browser.

@lancejpollard
Copy link
Author

But, it looks like it only happens with an external repo? Not sure.

@lancejpollard
Copy link
Author

lancejpollard commented Oct 17, 2017

This repo demonstrates the bug: https://github.com/lancejpollard/next-2-repos cc @giuseppeg

@lancejpollard lancejpollard changed the title Warning: Text content did not match. Server: "...css..." FOUC: Warning: Text content did not match. Server: "...css..." Oct 17, 2017
@giuseppeg
Copy link
Contributor

@lancejpollard first thing I noticed is that transform-react-jsx is transforming JSX to React.createElement calls and therefore styled-jsx is not capable of transpiling your library and app code (since it only understands JSX). Try to pass that after styled-jsx is done doing its work. Also beware that Babel merges visitors and often this optimization results in nasty bugs that are hard to debug/figure out - typically some plugins visitors end up never executing because swallowed or overridden by other plugins' ones.

Also make sure that you always use the latest version of styled-jsx - in 2 beta there was a bug which caused fouc indeed. Though it seems that in your app it resolves to 2.1.1 nonetheless.

That said, in case you still see FOUC let me know and I will try to take a look - any help is appreciated ofc, you are all pretty smart folks so I believe that you can debug as I would do too :)

Check with the Next.js folks and see whether Next (OR your custom server) encodes SSR code also.

@giuseppeg
Copy link
Contributor

By the way you might need to export styled-jsx/server's flushToHTML in your library so that the consumer app can render your styles on the server

@lancejpollard
Copy link
Author

lancejpollard commented Oct 17, 2017

Thanks for the help. One thing is I can't seem to leave the raw JSX in a separate module, get this error: #3088. So catch 22 sort of. cc @arunoda

@giuseppeg
Copy link
Contributor

@lancejpollard I guess because Next doesn't transpile node_modules. I believe that if your invert the plugins order in your example repo it might work: --plugins=styled-jsx/babel,transform-react-jsx

@lancejpollard
Copy link
Author

Yeah, maybe some way could be added to handle that. Changing the order didn't work.

@lancejpollard
Copy link
Author

lancejpollard commented Oct 17, 2017

@arunoda maybe we can have this be configurable somehow (excluding node_modules):

https://github.com/zeit/next.js/blob/master/server/build/webpack.js#L196-L288

This is the output from trying to load the module without transpiling:

ModuleParseError: Module parse failed: ~/next-2-repos/repo-b/index.js Unexpected token (10:11)
You may need an appropriate loader to handle this file type.
|     let { color, title } = this.props
| 
|     return <div>
|       <Head>
|         <title>{ title }</title>
    at doBuild (~/next-2-repos/repo-a/node_modules/webpack/lib/NormalModule.js:303:19)
    at runLoaders (~/next-2-repos/repo-a/node_modules/webpack/lib/NormalModule.js:209:11)
    at ~/next-2-repos/repo-a/node_modules/loader-runner/lib/LoaderRunner.js:370:3
    at iterateNormalLoaders (~/next-2-repos/repo-a/node_modules/loader-runner/lib/LoaderRunner.js:211:10)
    at ~/next-2-repos/repo-a/node_modules/loader-runner/lib/LoaderRunner.js:202:4
    at ~/next-2-repos/repo-a/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:70:14
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickDomainCallback (internal/process/next_tick.js:218:9)

@giuseppeg
Copy link
Contributor

without transpiling

oh yea I meant, if you run yarn build in repo-b and use the built version.

@lancejpollard
Copy link
Author

I tried tinkering with the webpack.js file but to no avail. Maybe someone could point me to where this sort of feature (loading external modules as jsx) could be implemented (what changes would need to be made).

@giuseppeg
Copy link
Contributor

@lancejpollard yeah I am afraid that Next won't transpile node_modules. Maybe you can hack something together using babel-require but these are all ideas/assumptions. Probably #3088 or the slack channel is the best place to discuss about this with someone like @arunoda, @rauchg or @nkzawa who definitely have more knowledge of the internals of Next.js

@timneutkens
Copy link
Member

We're going to implement transpiling node_modules in a future release. Till then you can use something like this example: #3732

@ghost
Copy link

ghost commented Jul 18, 2018

Still happening.

With the basic template provided by the tutorial and the following controller:

import React from 'react'
export default () => (
  <div>
    <script>{`

var Input = React.createClass({
  getInitialState: function() {
    return {typed: ''};
  },
  onBlur: function(event) {
    this.setState({typed: event.target.value});
  },
  render: function() {
    return <div>
        <input type="text" onBlur={this.onBlur.bind(this)}/>
        You typed: <code>{this.state.typed}</code>
      </div>
  }
});
React.render(<Input/>, document.querySelector('div'));

    `}</script>
  </div>
)

Browser somehow receives html encoded version of characters.

@Weipengzhou
Copy link

I want to know what method you used to solve last.

@ghost
Copy link

ghost commented Aug 1, 2018

@Weipengzhou if by last you mean mine then I didn’t work out a solution yet. If I do I will post updates here.

@pushkine
Copy link

.side-pannel > * {
        padding:0.3em 0;
    }

becomes

.side-pannel &gt; *{
        padding:0.3em 0;
    }

gives a warning but still applies the padding ( next 7.0.2 )

@mununki
Copy link

mununki commented Dec 5, 2018

I have the same issue still. I import the css style in string from external *.js file. It give me a warning.

Server: "#layout {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) 2fr;
  grid-template-areas: &quot;header header&quot; &quot;category content&quot; &quot;footer footer&quot;;
}"

Client: "#layout {
  display: grid;
  grid-template-columns: minmax(200px, 1fr) 2fr;
  grid-template-areas: "header header" "category content" "footer footer";
}"

Fortunately, css style is working...

I'm using next 7.0.2 now. But I didn't encounter this issue when I using next 6.

@jeanlescure
Copy link

I have the same issue

body > div {
  /* ... */
}

becomes

body &gt; div {
  /* ... */
}

Even though the style was being applied properly, the warning was disruptive enough (I use the console extensively in my day-to-day development) for me to try the following:

// Originally I was applying my theme like this from a HOC that wraps "themeable" components
<style
  jsx="true"
  global="true"
>
  {`${theme.shades[shade][componentName]}`}
</style>

// Replaced with this awful thing
<style
  jsx="true"
  global="true"
  dangerouslySetInnerHTML={{__html: theme.shades[shade][componentName]}}
/>

This got rid of the warning but now the "de-dupe" functionality is broken and I get as many style definitions for each component as the number of said component's instances, which just kills performance at the scale of apps I'm working with.

@lock lock bot locked as resolved and limited conversation to collaborators Dec 12, 2019
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

8 participants