全局CSS必须在_pages Router的_app.js或App Router的app/layout.tsx顶层静态导入,因Next.js依赖静态分析提取样式;组件内import会致FOUC或报错,且两套路由系统样式隔离。

全局CSS必须在_app.js或app/layout.tsx顶层导入
Next.js禁止在组件、页面或任意JS文件中import全局CSS,根本原因是构建时样式收集机制依赖静态分析——它只扫描根布局文件的顶层import语句。一旦import '../styles/global.css'出现在函数体、条件分支、useEffect或动态import()里,Next.js就无法在服务端渲染(SSR)阶段提取并内联样式,导致首屏无样式(FOUC)或构建报错Global CSS cannot be imported from files other than your Custom _app.js。
Pages Router和App Router的入口位置完全不同
混用路由结构是报错最常见原因:
- 用的是App Router(项目含
app/目录),却还在pages/_app.js里写import——Next.js 13+直接忽略该文件,且拒绝从非根布局处加载全局CSS - Pages Router下,
pages/_app.js是唯一合法位置;App Router下,app/layout.tsx(或.js)才是唯一入口,且import必须在文件首行,前面不能有任何代码(包括注释) - 同时存在
pages/和app/时,两套样式系统完全隔离:Pages页面走_app.js,App页面走app/layout.tsx,互不感知
为什么不能在组件里import非模块CSS
非模块CSS(即.css而非.module.css)没有作用域隔离,如果允许在组件中随意引入,会破坏构建时的CSS顺序控制和去重逻辑:
- 多个组件import同一份
base.css,会导致样式重复注入(DevTools里看到多个) - 服务端无法判断哪些CSS属于“关键样式”,无法做首屏内联优化
- SSR过程中,组件可能被多次实例化(如列表渲染),重复import会触发多次样式注册,引发hydration mismatch
- Webpack/Vite样式插件只监听顶层静态
import,组件内import会被当作普通模块处理,CSS规则无法进入样式提取管道
真正容易被忽略的硬性限制
即使路径和位置都对,以下细节仍会导致失败:
-
globals.css里写了@layer components以外的PostCSS特性(比如@custom-media),而postcss.config.js没配对应插件,构建直接中断 - CSS文件名带
global但后缀是.module.css——Next.js按后缀判定模块化行为,.module.css强制走局部作用域,全局规则失效 - 用了Tailwind但
@tailwind base、@tailwind components、@tailwind utilities没全写在同一个CSS文件里,拆开放置会导致部分层丢失 - 在
app/layout.tsx里加了'use client'——CSS导入是服务端行为,加这个指令会让整个layout变成客户端组件,样式无法SSR注入
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











