我遇到一个问题,即客户端渲染的组件类名(使用makeStyles创建的自定义类名)的格式为jss1234
,但是在服务器上渲染时,它们的格式为makeStyles-name-1234
。然后补水会引起问题。
我遵循了服务器端的设置:https://material-ui.com/guides/server-rendering/#handling-the-request简直就是信。
我的客户端入口点看起来像:
const Main = () => {
useEffect(() => {
// clean up any server side generated styles
const jssStyles = document.querySelector('#jss-server-side');
if (jssStyles) {
jssStyles.parentNode.removeChild(jssStyles);
}
}, []);
return (
<ThemeProvider theme={ theme }>
<BrowserRouter>
<App />
</BrowserRouter>
</ThemeProvider>
);
};
ReactDOM.hydrate(<Main />, root);
这只是生产中的问题,我确保服务器和客户端代码都具有process.env.NODE_ENV === 'production'
。
我不介意我的类名是哪种格式,只要它们是一致的即可。我尝试使用StylesProvider并创建一个新的generateClassName函数来强制一种或另一种方法,但是它似乎不起作用。客户端始终为jss
,服务器始终为makeStyles
前缀。
还有其他配置方法吗?
谢谢,我会在发现问题时用更多信息更新问题。
更新
仔细检查后,似乎无法覆盖generateClassName函数,我传入了一个并生成了一个函数,但并不是那个被调用的函数。
我有以下内容:
const generateClassName = createGenerateClassName({ disableGlobal: true });
const css = new ServerStyleSheets({ generateClassName });
const markup = ReactDOMServer.renderToString(
css.collect(
<StylesProvider generateClassName={ generateClassName }>
<ThemeProvider theme={ theme }>
...
和我的客户中
const generateClassName = createGenerateClassName({ disableGlobal: true });
return (
<StylesProvider generateClassName={ generateClassName }>
<ThemeProvider theme={ theme }>
...
但是disableGlobal永远不会生效,看起来好像它从未真正使用过此功能。我必须缺少一些配置,但是我发现有关此内容的文档有些零散,似乎暗示我不需要在具有新API的服务器上使用StylesProvider。
提前谢谢。
答案 0 :(得分:0)
事实证明,这确实是NODE_ENV的问题。
在我的情况下,我是使用webpack而不是外部节点模块(使用webpack nodeExternals)来编译客户端代码。执行此操作的命令类似于:
NODE_ENV=production webpack ... && node server.js
将这些更改为单独的npm任务或类似的内容
NODE_ENV=production webpack ... && NODE_ENV=production node server.js
这解决了问题,并且我已经能够从代码中删除StylesProvider,因为新的MUI v4 API不需要它。
感谢并继续努力。
答案 1 :(得分:0)
我遇到了一些问题。我遵循https://material-ui.com/guides/server-rendering/#handling-the-request中的确切教程。开发版本运行良好,但是在节点上运行生产版本时,服务器端渲染使用开发类名称,从而导致水合类不匹配。
我通过在生产服务器上的节点引导程序中包含NODE_ENV环境变量来解决此问题。
NODE_ENV=production node server.js