You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js集成Material-ui样式失效,报className不匹配警告求助

解决Next.js + Material-UI 服务端/客户端 className 不匹配及样式失效问题

我之前也碰到过几乎一模一样的问题,结合你的代码和描述,核心问题可以拆成几个点来修复:

1. 自定义 Server 里的致命错误:dev 变量判断完全写反

你的 server.js 里这一行逻辑搞反了:

const dev = process.env.NODE_ENV === "production";

这意味着当你线上设置 NODE_ENV=production 时,Next.js 反而会以开发模式启动。而开发模式下 Material-UI 的 JSS 会生成动态类名,和生产模式的静态哈希类名完全不匹配,直接导致 className did not match 警告和样式失效。

修正后的 server.js 应该是:

const express = require("express");
const next = require("next");
const port = parseInt(process.env.PORT, 10) || 3000;
// 正确逻辑:只有开发环境下 dev 才为 true
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

app.prepare().then(() => {
  const server = express();

  server.get("*", (req, res) => {
    return handle(req, res);
  });

  server.listen(port, err => {
    if (err) throw err;
    console.log(`> Ready on http://localhost:${port}`);
  });
});

2. 修复依赖版本不匹配问题

你提到使用的是 Material-UI 3.9.3,但 package.json 里 @material-ui/core 用的是 "next"(会自动安装 beta 版),这会和 Next.js 8.0.4 产生版本冲突。需要统一指定稳定兼容的版本:

更新后的 package.json 依赖部分:

{
  "dependencies": {
    "@material-ui/core": "3.9.3",
    "@material-ui/icons": "^3.0.2",
    "@material-ui/styles": "3.0.0-alpha.10", // 和 3.9.3 匹配的样式包版本
    "apollo-boost": "^0.3.1",
    "clsx": "^1.0.4",
    "express": "^4.16.4",
    "graphql": "^14.2.0",
    "isomorphic-unfetch": "^3.0.0",
    "joi-browser": "^13.4.0",
    "jss": "^10.0.0", // 兼容 Material-UI 3.x 的 JSS 版本
    "next": "8.0.4",
    "prop-types": "^15.7.2",
    "react": "^16.8.6", // 和 Next.js 8.0.4 匹配的 React 版本
    "react-apollo": "^2.5.3",
    "react-dom": "^16.8.6"
  }
}

执行 npm install 重新安装依赖,确保版本统一。

3. 配置 _app.js 处理服务端样式收集

为了让服务端渲染的样式能正确传递到客户端,需要在 pages/_app.js 中使用 Material-UI 的 ServerStyleSheets 来收集服务端样式:

创建或修改 pages/_app.js:

import React from 'react';
import App, { Container } from 'next/app';
import { ThemeProvider } from '@material-ui/core/styles';
import createMuiTheme from '@material-ui/core/styles/createMuiTheme';
import { ServerStyleSheets } from '@material-ui/styles';

// 自定义主题(可根据你的需求调整)
const theme = createMuiTheme({
  palette: {
    primary: {
      main: '#1976d2',
    },
  },
});

class MyApp extends App {
  static async getInitialProps({ Component, ctx }) {
    const sheets = new ServerStyleSheets();
    const pageProps = Component.getInitialProps ? await Component.getInitialProps(ctx) : {};

    // 拦截页面渲染,收集服务端样式
    const originalRenderPage = ctx.renderPage;
    ctx.renderPage = () =>
      originalRenderPage({
        enhanceApp: (App) => (props) => sheets.collect(<App {...props} />),
      });

    return {
      pageProps,
      // 将收集到的样式传递给客户端
      styles: sheets.getStyleElement(),
    };
  }

  render() {
    const { Component, pageProps, styles } = this.props;
    return (
      <Container>
        {/* 注入服务端渲染的样式,避免客户端重绘时样式丢失 */}
        {styles}
        <ThemeProvider theme={theme}>
          <Component {...pageProps} />
        </ThemeProvider>
      </Container>
    );
  }
}

export default MyApp;

4. 线上部署验证步骤

  1. 先在本地测试生产模式:
    npm run build
    npm run prod_start
    
    访问页面确认警告消失,样式正常加载。
  2. 线上服务器执行相同流程:
    • 拉取最新代码
    • 执行 npm install
    • 执行 npm run build
    • 用 PM2 启动服务时,确保 NODE_ENV=production 环境变量已正确设置(可以在 PM2 配置文件里指定)

做完这些步骤后,应该就能彻底解决 className did not match 的警告和样式失效问题了。

内容的提问来源于stack exchange,提问作者Rigal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:52:37