I am writing a React app that uses server-side rendering. I am following the instruction here to set up a file.
Here is my .babelrc
configuration file
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": { "version": 3, "proposals": true },
"targets": {
"browsers": "> 1%, not ie 11, not op_mini all",
"node": 13
}
}
],
"@babel/preset-react"
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-transform-runtime",
[
"import",
{
"libraryName": "@material-ui/icons",
"libraryDirectory": "utils", // default: lib
"camel2DashComponentName": false // default: true
},
"@material-ui/icons"
]
]
}
And this is webpack.config.js
file
const path = require("path");
const nodeExternals = require("webpack-node-externals");
const commonConfig = {
devtool: "source-map",
module: {
rules: [{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }]
},
resolve: {
alias: {
"@material-ui/core": "@material-ui/core/es"
}
}
};
module.exports = [
{
...commonConfig,
entry: "./src/client",
output: {
path: path.resolve(__dirname, "public")
}
},
{
...commonConfig,
target: "node",
entry: "./src/server",
output: {
path: path.resolve(__dirname, "server")
},
externals: [nodeExternals()]
}
];
(Here is the full code in CodeSandBox and here is in Github if you want to try out)
The problem appear is when I bundle up the file, in development mode, everything work just fine. But when I try production mode, the CSS part starts to behave weirdly. When the file is first loaded from localhost
, it is styled correctly (this happens in a very short time), then the style goes wrong as some styling is missing.
When I try to investigate, I find that all the style that is missing is the part I wrote with makeStyles()
. All the built-in styles work just fine.
I tried to remove all the resolve
property in webpack.config.js
following this post, but it doesn't work. No matter what I try to change that property, nothing happens.
So now the only way I found that can make the app work in production build is to remove the code that removes the styling file (you can find that part at the end of client.js
file), but I'm not sure what is the result of doing so.
So my questions are:
Why there is such a difference between two modes, development and production? I get that the production mode will include some minification, tree shaking, etc., and the development has most of that except for minification. So why there is a difference?
Edit: I found two possible and workable fixes for this bug: one is to stop removing those CSS files (code that I wrote in client.js
file); the other one is to remove the nodeExternal()
plugin in webpack.config.js
and bundle everything for the server file. What do you think ?
I had a similar issue, although without server-side rendering. It was caused by a different order of stylesheets in dev and prod environments, causing unwanted overwrites. In dev env all stylesheets created by makeStyles()
were injected after ALL MUI stylesheets, but in production they were mixed.
Solution:
Add an option: { index: 1 }
to all makeStyles()
invocations, in order to place those sheets after the MUI sheets which have an index of 0 (by default). This optional argument is passed directly to underlying JSS's jss.createStyleSheet()
and dictates the injection order:
const useStyles = makeStyles(
(...), // styles
{ index: 1 }, // optional argument for JSS, to set position after MUI stylesheets
)