实质性UI中断了生产中的NextJS应用

时间:2020-08-09 09:10:44

标签: reactjs material-ui next.js production-environment

我创建了一个使用服务器端渲染和Material UI的NextJS应用。在开发中效果很好。

当我运行“下一个版本”时,该应用程序会编译并正确生成。当我使用NODE_ENV = production运行它时,网页呈现得很好,但是许多功能不再起作用。例如:

  1. Material UI的“隐藏”组件即使在应有的情况下也永远不会显示其嵌套的任何子组件(在我的开发应用程序中,它会根据屏幕尺寸隐藏并显示某些div)。

  2. 网页上的所有按钮均无效。所有这些按钮都具有“ onClick”事件,单击这些事件时,其回调函数会以某种方式修改React状态对象。但是,单击这些时什么也不会发生。状态保持不变,因此我假设这些单击事件发生时永远不会调用这些函数。对于Material UI的Button组件以及普通的旧HTML按钮(如JSX),都是如此。

当我在笔记本电脑上以开发模式运行此程序时,一切工作都很好。但是,当我构建NextJS应用并将其以生产模式部署到服务器时,遇到了上面列出的问题。到目前为止,我的研究仅发现构建期间类名冲突的可能性(在Material UI的“常见问题”页面上已说过)。有人遇到过和我一样的问题吗?

编辑:我刚刚启动了一个准系统NextJS应用程序,该应用程序仅包含一个索引页和具有一个状态参数和一个用于通过onClick事件修改参数的按钮的最小依赖项。我有同样的问题。该按钮在开发中有效,但在生产中无效。因此,这将是NextJS问题而不是Material UI问题。但这仍然不能解释为什么不管屏幕大小如何,Material UI的“隐藏”组件始终保持隐藏状态。也许既是Next JS问题,又是Material UI问题。

3 个答案:

答案 0 :(得分:0)

关于第一个问题,由于您打开了ssr,因此材料ui无法判断服务器端的断点。这是一个官方示例。server-sider-rendering。您需要根据UA标头确定用户设备,以确定页面大小。使用匹配项来确定您需要显示的内容

答案 1 :(得分:0)

我认为这可以为您提供帮助。 在_document.js

import React from 'react';
import Document, {
  Html, Main, NextScript,
} from 'next/document';
import { ServerStyleSheets } from '@material-ui/core/styles';

export default class MyDocument extends Document {
  render() {
    return (
      <Html lang="en">
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

// `getInitialProps` belongs to `_document` (instead of `_app`),
// it's compatible with server-side generation (SSG).
MyDocument.getInitialProps = async (ctx) => {

  // Render app and page and get the context of the page with collected side effects.
  const sheets = new ServerStyleSheets();
  const originalRenderPage = ctx.renderPage;

  ctx.renderPage = () => originalRenderPage({
    enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
  });

  const initialProps = await Document.getInitialProps(ctx);

  return {
    ...initialProps,
    // Styles fragment is rendered after the app and page rendering finish.
    styles: [...React.Children.toArray(initialProps.styles), sheets.getStyleElement()],
  };
};

并添加_app.js

React.useEffect(() => {
  // Remove the server-side injected CSS.
  const jssStyles = document.querySelector('#jss-server-side');
  if (jssStyles) {
    jssStyles.parentElement.removeChild(jssStyles);
  }
}, []);

希望它能起作用!

答案 2 :(得分:0)

_document.js->用于SSR的MaterialUI样式。

import React from 'react'
import NextDocument from 'next/document'
import { ServerStyleSheet as StyledComponentSheets } from 'styled-components'
import { ServerStyleSheets as MaterialUiServerStyleSheets } from '@material-
ui/styles'

export default class Document extends NextDocument {

static async getInitialProps(ctx) {
const styledComponentSheet = new StyledComponentSheets()
const materialUiSheets = new MaterialUiServerStyleSheets()
const originalRenderPage = ctx.renderPage

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

  const initialProps = await NextDocument.getInitialProps(ctx)

  return {
    ...initialProps,
    styles: [
      <React.Fragment key="styles">
        {initialProps.styles}
        {materialUiSheets.getStyleElement()}
        {styledComponentSheet.getStyleElement()}
      </React.Fragment>,
    ],
  }
} finally {
  styledComponentSheet.seal()
}
}
}