Next.js dev 下 CSS @import 链改了没效果?根因是 .next 缓存没失效
加了一个侧边栏折叠功能。JS 那侧改动——组件渲染、图标切换——HMR 秒到,一切正常。但匹配的 CSS:grid-template-columns 收窄、sidebar-rail 宽度、内容区 overflow: hidden——全部没有生效。三轮排查都指向「CSS 写错了/选择器优先级冲突/浏览器缓存」,但硬刷新、强制清缓存之后依然是老样子。直到用 curl 把编译产物拉下来一 grep,才发现那两条新规则根本不在编译后的 bundle 里。
现象
项目的 CSS 组织方式是 app/globals.css 里通过 @import 引入各功能分片:
/* globals.css */
@import './styles/06-workspace-chrome.css';在 06-workspace-chrome.css 里新增了两个类:
.shell--collapsed {
grid-template-columns: 40px minmax(0, 1fr);
}
.sidebar-rail {
width: 40px;
}重启 next dev,硬刷新浏览器——依然无效。DevTools 里对应元素找不到这两条规则,甚至在 Sources 面板翻遍所有 CSS chunk 也看不到它们。
根因
next dev 的增量编译对 JS 模块图做了精细的依赖追踪,但对 CSS @import 链的追踪是不完整的。具体来说:
- 通过 JS
import './x.css'引入的样式:文件变动 → HMR 能感知到 → 重新编译。 - 通过 CSS
@import从另一个 CSS 文件间接引入的样式:.next缓存里已经有一份编译好的全局 CSS bundle,当被@import的那层文件发生变化时,缓存不会失效,重启 dev server 也不会强制重编译这条链路。
结果就是:旧规则(缓存里已有的)继续生效,新规则(缓存生成之后才写进去的)永远不会出现在 bundle 里——除非把缓存整个删掉。
next dev 重启时会复用 .next 目录里已编译的产物。对于通过 CSS @import 间接引入的文件,文件内容变了,缓存里的 bundle 却不会重新生成。这让「重启没用」成为一个强烈的误导信号——你会以为问题在 CSS 本身,而不是缓存。
排查:先确认是缓存问题,不是 CSS 写错了
不要靠 DevTools 猜——直接把编译产物拉下来验证:
# 1. 从页面 HTML 里取出实际的 CSS bundle 路径
CSS_PATH=$(curl -s http://localhost:3000/ \
| grep -oE '/_next/static/css/[^"]+\.css' | head -1)
# 2. 把 bundle 下载到本地
curl -s "http://localhost:3000${CSS_PATH}" -o /tmp/out.css
# 3. 新规则是否编译进去了
grep -c "shell--collapsed" /tmp/out.css # 0 = 没编译进去
# 4. 旧规则是否在(同一文件里)
grep -c "dossier-shell" /tmp/out.css # >0 = 文件确实被 @import如果旧规则存在、新规则缺失,且它们来自同一个文件——那就是缓存问题,和 CSS 语法无关。
正解
确认是缓存问题后,操作很简单:
# 杀掉 dev server、删缓存、重新启动
lsof -ti:3000 | xargs kill -9
rm -rf .next
npm run dev启动完成(看到 Ready in)后,再跑一次 curl+grep 验证:
CSS_PATH=$(curl -s http://localhost:3000/ \
| grep -oE '/_next/static/css/[^"]+\.css' | head -1)
curl -s "http://localhost:3000${CSS_PATH}" -o /tmp/out.css
grep -n -A 5 "shell--collapsed" /tmp/out.cssdev CSS 是未压缩的,能直接读到完整的声明块。确认规则在 bundle 里之后,浏览器硬刷新(Cmd+Shift+R)即可。
CSS 新增规则在 next dev 里不生效时,第一反应应该是清 .next 缓存,而不是找选择器优先级或浏览器缓存的问题。next build 每次都全量重编,生产环境不受影响——这是纯 dev-only 的陷阱。
补充:什么时候需要做这一步
记住这条心智模型:
- JS 文件 /
import './x.css'方式引入的 CSS → HMR 有效,可以热更。 - CSS 文件里通过
@import间接引入的 CSS → 改了不一定能感知到,.next缓存可能包住旧版本。
当你发现「JS 改动生效了,配套的 CSS 没有」,第一步就是清缓存,别在 DevTools 里绕弯子。
一句话外卖
在
next dev里,CSS@import链上的文件改动不会让.next缓存失效;症状是新规则蒸发、老规则健在,rm -rf .next重启是唯一正解。