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,通过给根元素切换类名来切换主题变量,体验更流畅:
- 统一编写全局样式(用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';
- 在_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
相关产品推荐
相关产品推荐

