question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Server Rendering / SSR : CSS disappears upon js load, only in prod not dev

See original GitHub issue
  • This is not a v0.x issue.
  • I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

The css must not disappear when the js was loaded.

Current Behavior

The css disappears. This does not happen in webpack development, but only in production.

Steps to Reproduce

I was following the examples from the docs.

I noticed that the one from our docs here at https://material-ui.com/guides/server-rendering/ is different from the one from this github repo which is https://github.com/mui-org/material-ui/blob/master/docs/src/pages/guides/server-rendering/server-rendering.md, in which case I ended up following the latter since it solved some initial problems such as css name mismatches between the server & client. I also ensured that I’ve read the Troubleshooting part and didn’t miss what’s documented already.

The webpack.config.js I’m using is provided below, and I also tried commenting out the following parts related to splitChunks and runtimeChunk, but the css still disappears when the bundle js is loaded in the production build:

    // ...
    optimization: {
      /*
       * SplitChunks: {
       * chunks: 'all'
       * },
       * runtimeChunk: true,
       */
      minimize: Boolean(mode === 'production'),
      minimizer: [
        new UglifyJSWebpackPlugin({
          parallel: os.cpus().length,
          cache: true,
          uglifyOptions: {
            output: {
              comments: false
            },
            compress: {
              dead_code: true
            },
            mangle: true
          },
          sourceMap: true
        })
      ]
    },
    // ...

App.jsx:

import React from 'react';
import Button from '@material-ui/core/Button';
const App = () => (
  <Button variant="contained" color="primary" onClick={() => console.log('Clicked!')}>
    Hello World
  </Button>
);
export default App;

Client.jsx:

import '@babel/polyfill';
import React from 'react';
import { hydrate } from 'react-dom';
import {
  MuiThemeProvider,
  createMuiTheme,
  createGenerateClassName
} from '@material-ui/core/styles';
import green from '@material-ui/core/colors/green';
import red from '@material-ui/core/colors/red';
import JssProvider from 'react-jss/lib/JssProvider';
import App from './App';

class Main extends React.Component {
  componentDidMount () {
    const jssStyles = document.getElementById('jss-server-side');
    if (jssStyles && jssStyles.parentNode) {
      jssStyles.parentNode.removeChild(jssStyles);
    }
  }
  render () {
    return <App />;
  }
}
const theme = createMuiTheme({
  palette: {
    primary: green,
    accent: red,
    type: 'light'
  }
});
const generateClassName = createGenerateClassName({
  dangerouslyUseGlobalCSS: false
});
hydrate(
  (
    <JssProvider generateClassName={generateClassName}>
      <MuiThemeProvider theme={theme}>
        <Main />
      </MuiThemeProvider>
    </JssProvider>
  ),
  document.querySelector('#root'),
);

SSR.jsx:

import React from 'react';
import { renderToString } from 'react-dom/server';
import { SheetsRegistry } from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import {
  MuiThemeProvider,
  createMuiTheme,
  createGenerateClassName
} from '@material-ui/core/styles';
import green from '@material-ui/core/colors/green';
import red from '@material-ui/core/colors/red';
import App from '../client/App';
const handleRender = (req, res) => {
  const sheetsRegistry = new SheetsRegistry();
  const sheetsManager = new global.Map();
  const theme = createMuiTheme({
    palette: {
      primary: green,
      accent: red,
      type: 'light'
    }
  });
  const generateClassName = createGenerateClassName({
    dangerouslyUseGlobalCSS: false
  });
  const html = renderToString(
    <JssProvider registry={sheetsRegistry} generateClassName={generateClassName}>
      <MuiThemeProvider theme={theme} sheetsManager={sheetsManager}>
        <App />
      </MuiThemeProvider>
    </JssProvider>
  );
  const css = sheetsRegistry.toString();
  const page = `
    <!doctype html>
    <html>
      <head>
        <title>Material-UI</title>
      </head>
      <body>
        <div id="root">${html}</div>
        <style id="jss-server-side">${css}</style>
        <script src="/scripts/main.js" defer></script>
        <script src="/scripts/vendors~main.js" defer></script>
        <script src="/scripts/runtime~main.js" defer></script>
      </body>
    </html>
  `;
  res.send(page);
};
export default handleRender;
//...
import SSR from './SSR';
const app = express();
// ...
app.use(SSR);

webpack.config.js:

const os = require('os');
const path = require('path');
const webpack = require('webpack');
const UglifyJSWebpackPlugin = require('uglifyjs-webpack-plugin');
const webpackNodeExternals = require('webpack-node-externals');
const Client = (env, argv) => {
  const { mode } = argv;
  return {
    devtool: mode === 'development'
      ? 'source-map'
      : false,
    entry: [
      '@babel/polyfill',
      './src/client/Client.jsx'
    ],
    resolve: {
      extensions: [
        '.js',
        '.jsx'
      ]
    },
    module: {
      rules: [
        {
          enforce: 'pre',
          test: /\.(js|jsx)$/,
          use: 'eslint-loader',
          exclude: /node_modules/
        },
        {
          test: /\.worker\.js$/,
          use: [
            {
              loader: 'worker-loader',
              options: {
                name: '[name].js',
                publicPath: '/scripts/'
              }
            }
          ]
        },
        {
          test: /\.(js|jsx)$/,
          use: 'babel-loader',
          exclude: /node_modules/
        },
        {
          test: /\.(css)$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        }
      ]
    },
    plugins: [
      new webpack.DefinePlugin({
        ENVIRONMENT: JSON.stringify(mode)
      })
    ],
    optimization: {
      splitChunks: {
        chunks: 'all'
      },
      runtimeChunk: true,
      minimize: Boolean(mode === 'production'),
      minimizer: [
        new UglifyJSWebpackPlugin({
          parallel: os.cpus().length,
          cache: true,
          uglifyOptions: {
            output: {
              comments: false
            },
            compress: {
              dead_code: true
            },
            mangle: true
          },
          sourceMap: true
        })
      ]
    },
    output: {
      path: path.join(__dirname, '/dist/client'),
      publicPath: '/scripts/'
    },
    stats: 'minimal'
  };
};
const Server = (env, argv) => {
  const { mode } = argv;
  return {
    devtool: mode === 'development'
      ? 'source-map'
      : false,
    entry: ['./src/server/Server.js'],
    resolve: {
      extensions: [
        '.js',
        '.jsx'
      ]
    },
    target: 'node',
    node: {
      __dirname: false,
      __filename: false
    },
    externals: [webpackNodeExternals()],
    module: {
      rules: [
        {
          enforce: 'pre',
          test: /\.(js|jsx)$/,
          use: 'eslint-loader',
          exclude: /node_modules/
        },
        {
          test: /\.(js|jsx)$/,
          use: 'babel-loader',
          exclude: /node_modules/
        }
      ]
    },
    plugins: [
      new webpack.DefinePlugin({
        ENVIRONMENT: JSON.stringify(mode),
      })
    ],
    output: {
      path: path.join(__dirname, '/dist/server')
    }
  };
};
module.exports = [
  Client,
  Server
];

Context

Nothing much special just App.jsx with a button.

When the bundle js is loaded, the components work great. Their styling just disappears, that’s the problem.

(preparing the reproduction repo right now!)

Your Environment

Tech Version
Material-UI v3.0.3
React 16.5.1
Browser Chrome x64 Latest, Windows

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

2reactions
speedy250commented, Nov 1, 2018

Adding NODE_ENV=production to my server script has fixed the issue for me. Script command is now NODE_ENV=production run-s build start-prod

1reaction
oliviertassinaricommented, Sep 18, 2018

It was working all fine on my side with your reproduction. webpack has nothing to do with it. It’s about using the same generator on the client and the sever (same options, same node env, same version).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Server Rendering / SSR : CSS disappears upon js load, only ...
The css disappears. This does not happen in webpack development, but only in production. Steps to Reproduce. I was following the examples from ......
Read more >
Styles not applied in first load using Next.js & Material-UI
This might be due to SSR (Server Side Rendering) support in Next.js, as material-ui uses JSS for styling, so the styles get loaded...
Read more >
How To Render CSS on React App Servers | DigitalOcean
In this article, we will go over the challenges of rendering CSS and then use styled-components and styled-jsx on the server in a...
Read more >
Next.js and Styled-Components: style loading issue
js app but can't get the styles to load properly? This is because the server-side rendering does not fetch the styles before rendering...
Read more >
Keeping Server-Side Rendering Cool With React Hydration
The purpose of this article is to share some helpful things to keep in mind to render a seamless experience as a Server-Side...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found