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

Next.js中如何动态导入全局CSS?条件导入报错求助

解决方案

你遇到的错误是因为ES模块规范要求import声明必须放在文件顶层,不能嵌套在if/else这类代码块里。下面提供几种可行的解决方法:

方法一:使用动态导入(客户端异步加载)

利用Next.js支持的动态导入特性,在客户端useEffect中根据Cookie加载对应CSS:

import { useEffect } from 'react';
import Cookies from 'js-cookie';

function MyApp({ Component, pageProps }) {
  useEffect(() => {
    const activeTheme = Cookies.get('theme');
    if (activeTheme === 'dark') {
      import('@/styles/core-dark.css');
      import('@/styles/theme-default-dark.css');
    } else {
      import('@/styles/core.css');
      import('@/styles/theme-default.css');
    }
  }, []);

  return <Component {...pageProps} />;
}

export default MyApp;

⚠️ 注意:动态导入是异步的,页面初始加载可能会有闪屏,适合对首屏体验要求不高的场景。

方法二:CSS变量+类名切换(推荐,无闪屏)

这种方式不需要条件导入CSS,通过给根元素切换类名来切换主题变量,体验更流畅:

  1. 统一编写全局样式(用CSS变量定义主题)
/* styles/core.css */
:root {
  --bg-primary: #ffffff;
  --text-primary: #111111;
  /* 其他主题相关变量 */
}

.dark {
  --bg-primary: #1a1a1a;
  --text-primary: #f5f5f5;
  /* 深色主题变量 */
}

/* 基础样式全部使用变量 */
body {
  background-color: var(--bg-primary);
  color: var(--text-primary);
  transition: all 0.3s ease;
}

同时导入所有主题相关的默认样式(无需条件导入):

import '@/styles/core.css';
import '@/styles/theme-default.css';
  1. 在_app.tsx中根据Cookie切换根元素类名
import { useEffect } from 'react';
import Cookies from 'js-cookie';
import '@/styles/core.css';
import '@/styles/theme-default.css';

function MyApp({ Component, pageProps }) {
  useEffect(() => {
    const activeTheme = Cookies.get('theme') || 'light';
    document.documentElement.classList.toggle('dark', activeTheme === 'dark');
  }, []);

  return <Component {...pageProps} />;
}

export default MyApp;

方法三:服务端注入主题(解决首屏闪屏)

如果需要在服务端就渲染正确主题,避免闪屏,可以在_document.tsx(Pages Router)或layout.tsx(App Router)中处理:

Pages Router(_document.tsx)

import Document, { Html, Head, Main, NextScript } from 'next/document';

class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    // 服务端读取Cookie
    const theme = ctx.req?.cookies.theme || 'light';
    return { ...initialProps, theme };
  }

  render() {
    return (
      <Html className={this.props.theme === 'dark' ? 'dark' : ''}>
        <Head>
          {/* 根据主题注入对应CSS */}
          {this.props.theme === 'dark' ? (
            <>
              <link rel="stylesheet" href="/styles/core-dark.css" />
              <link rel="stylesheet" href="/styles/theme-default-dark.css" />
            </>
          ) : (
            <>
              <link rel="stylesheet" href="/styles/core.css" />
              <link rel="stylesheet" href="/styles/theme-default.css" />
            </>
          )}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html>
    );
  }
}

export default MyDocument;

App Router(layout.tsx)

import { headers } from 'next/headers';

export default function RootLayout({ children }) {
  const cookieStore = headers().get('cookie');
  const theme = cookieStore?.split('; ').find(item => item.startsWith('theme='))?.split('=')[1] || 'light';

  return (
    <html className={theme === 'dark' ? 'dark' : ''}>
      <body>{children}</body>
    </html>
  );
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 18:05:26