_app.js 在 Next.js 13+ app 目录模式下被废弃,仅对 pages 目录生效;若项目使用 app/layout.tsx,则 _app.js 完全被忽略,其导入的全局 Sass 样式(如 globals.scss)不会注入,且无报错。

不能在 _app.js 中直接导入全局 Sass 样式(如 globals.scss)——Next.js 13+ 的 app 目录模式下,_app.js 已被废弃,且该文件在 app 目录中完全不生效。
为什么 _app.js 在 app 目录里不起作用
Next.js 13 引入 app 目录后,路由和布局逻辑彻底重构:_app.js 只对旧的 pages 目录有效。如果你项目使用的是 app/layout.tsx(绝大多数新项目),那么 _app.js 文件会被忽略,任何在里面写的 import '../styles/globals.scss' 都不会触发样式注入,控制台也不会报错,但样式就是不生效。
- 检查项目结构:存在
app/目录 → 必须用app/layout.tsx导入全局 Sass - 若同时存在
pages/和app/,两者共存但样式系统隔离,_app.js只影响pages/下的页面 - 强行保留
_app.js并期望它控制整个应用,会导致样式漏加载、SSR/CSR 不一致、热更新失效等问题
正确做法:在 app/layout.tsx 中导入 .scss 文件
这是 Next.js 官方唯一支持的全局 Sass 入口点。只要确保 Sass 依赖已安装(npm install sass),就可以直接 import 普通 .scss 文件(非模块化)。
- 路径必须是相对路径,从
app/layout.tsx出发可解析到,例如:import '@/styles/globals.scss'或import '../styles/globals.scss' - 文件名不限于
globals.scss,但建议语义清晰,避免与.module.scss混淆 - 导入语句必须放在
layout.tsx的顶层(不能包裹在组件函数内,也不能用dynamic import()) - 样式会注入到
,并在所有子路由中持久存在(注意:Next.js 不会在路由切换时卸载它,所以只放真正全局的重置、字体、主题变量等)
示例:app/layout.tsx
立即学习“前端免费学习笔记(深入)”;
import './globals.scss'
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="zh">
<body>{children}</body>
</html>
)
}
常见错误:Sass 编译失败或样式未渲染
即使路径和导入写对了,也可能遇到无声失败:
-
Cannot find module 'sass':运行npm install sass,不是sass-loader或node-sass(Next.js 内置支持sass包) - SCSS 语法报错但页面没提示:检查是否用了
@use或@forward引入了未安装的第三方库(如 Bootstrap Sass),这类导入在全局上下文中容易因路径或配置缺失而静默跳过 - 样式只在客户端生效、服务端无 CSS:确认没有在
layout.tsx中用条件判断包裹import(如if (typeof window !== 'undefined')),全局样式必须同步导入 - 字体或变量未生效:Sass 中的
@font-face或:root声明需位于顶层,不能嵌套在选择器内;CSS 自定义属性推荐用:root {}而非html {}
如果必须兼容 pages 和 app 目录
极少数混合迁移项目需要双入口,此时要分开处理:
-
app/layout.tsx:导入app/styles/globals.scss -
pages/_app.tsx:导入styles/globals.scss(仅作用于pages/下的页面) - 两个文件不能共用同一份 SCSS —— 因为
@import和@use行为不同,且变量作用域不互通,混用会导致重复定义或丢失
最稳妥的方式是逐步将 pages/ 迁移进 app/,长期维护两套全局样式成本很高,尤其涉及主题切换、RTL 支持等复杂场景。


















