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

Next.js使用getServerSideProps时全局CSS生产环境不加载问题

问题:Next.js生产环境下全局样式与_app.tsx未生效(自定义Express服务器)

场景复现

  • 全局样式定义在/styles/globals.css,并在_app.tsx中导入:
// import default style
import "../styles/globals.css";

function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />;
}

export default MyApp;
  • pages目录下pages/index.tsx代码:
export async function getServerSideProps({req, res }) {
  // Some fetch here

  return {
    props: {
      someProps: objectFromFetchThere,
    },
  };
}

const Home: NextPage<{ someProps: SomeProps[] }> = ({ someProps }) => {
  return (
    <>
      <Head>
        <title>Home page</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <Layout>
        // More code here
      </Layout>
    </>
  );
};

问题现象

  • 开发环境执行next dev:样式正常加载,getServerSideProps正常调用,功能完全正常。
  • 生产环境执行next build && NODE_ENV=production ts-node src/server.ts:全局样式未加载,_app.tsx完全不生效。

疑问:曾怀疑使用getServerSideProps的页面无法使用全局样式,但Next.js文档未找到相关限制说明。

自定义Express服务器代码

(async () => {
  try {
    const expressServer = express();
    await app.prepare();

    // Some custom routes defined over there like /facility - nothing that can overlap with styles.

    // Error middleware has to be used after other custom routes
    expressServer.use(
      (err: Error, req: Request, res: Response, next: NextFunction) => {
        console.error(err.stack);
        res.status(500).send("Unexpected error occurred.");
      }
    );

    expressServer.all("*", async (req: Request, res: Response) => {
      try {
        await handle(req, res);
      } catch (e) {
        console.error("Error occurred handling", req.url, e);
        res.statusCode = 500;
        res.end("internal server error");
      }
    });

    expressServer.listen(port, (err?: any) => {
      if (err) throw err;
      console.log(
        `> Ready on localhost:${port} - env ${process.env.NODE_ENV}`
      );
    });
  } catch (e) {
    console.error(e);
    process.exit(1);
  }
})();

问题根源

你的自定义Express服务器错误地将错误中间件放在了Next.js请求处理逻辑之前。Next.js的handle需要优先处理所有请求(包括静态资源请求,比如编译后的全局样式文件),而错误中间件的位置错误会导致请求被提前拦截,静态资源无法被正确解析,同时_app.tsx的全局逻辑也无法正常执行。

修复方案

调整中间件顺序,将错误处理中间件移到所有路由(包括Next.js的通配符路由)之后:

(async () => {
  try {
    const expressServer = express();
    await app.prepare();

    // 自定义路由放在最前面
    // Some custom routes defined over there like /facility - nothing that can overlap with styles.

    // 先注册Next.js的请求处理逻辑
    expressServer.all("*", async (req: Request, res: Response) => {
      try {
        await handle(req, res);
      } catch (e) {
        console.error("Error occurred handling", req.url, e);
        res.statusCode = 500;
        res.end("internal server error");
      }
    });

    // 错误中间件放在最后
    expressServer.use(
      (err: Error, req: Request, res: Response, next: NextFunction) => {
        console.error(err.stack);
        res.status(500).send("Unexpected error occurred.");
      }
    );

    expressServer.listen(port, (err?: any) => {
      if (err) throw err;
      console.log(
        `> Ready on localhost:${port} - env ${process.env.NODE_ENV}`
      );
    });
  } catch (e) {
    console.error(e);
    process.exit(1);
  }
})();

额外说明

  • getServerSideProps与全局样式完全不冲突,Next.js中所有页面(无论使用哪种数据获取方式)都可以正常使用_app.tsx导入的全局样式。
  • 生产环境下Next.js会将全局样式编译为静态资源,自定义服务器必须保证这些请求能被handle正确处理,中间件顺序错误会直接阻断静态资源的加载逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:25:23