Next+React项目引入多个module.scss后生产环境客户端JS失效问题
问题根因
这个是Next.js 10.x版本内置的CSS Modules处理逻辑,和Sass @extend 嵌套类组合使用时的已知打包Bug:
- Next 10生产构建阶段,处理带嵌套类的
@extend规则时,会生成异常的CSS Module导出对象,对象内会出现不符合预期的非法属性 - Next的客户端hydration逻辑在读取到异常的模块导出值时会静默失败,既不会抛出错误日志,也会中断后续所有客户端JS的执行
- 这也是为什么页面视觉渲染正常(服务端生成的HTML、CSS已经返回),但所有交互逻辑失效的原因:服务端渲染阶段不会校验CSS Module导出的结构,只有客户端执行时才会触发
- 单引入一个样式文件正常、引入两个就失效,是因为单个样式文件的异常导出值刚好没有触碰到hydration的校验边界,两个异常对象叠加后结构超出了Next 10模块解析逻辑的容错范围,直接中断了整个客户端JS bundle的执行
- 注释掉
.bar嵌套类后问题恢复,是因为去掉嵌套类后,@extend生成的CSS Module导出对象结构回归正常,hydration逻辑可以正常执行完成,后续JS也就正常运行了
可行修复方案
- 优先推荐替换
@extend写法,改用classnames组合类名实现相同效果,避免在CSS Module中使用Sass的@extend规则,符合CSS Module的最佳实践,也不会触发版本兼容问题 - 升级Next.js版本到12.x及以上,这个Bug在Next 11的后续小版本、12正式版中已经被官方修复,升级后保留现有
@extend写法也不会出现问题,同步升级@netlify/plugin-nextjs到适配对应Next版本的版本即可 - 如果暂时不能升级Next版本、也不想调整现有样式写法,可以在
next.config.js中添加配置,调整CSS Modules的解析规则规避问题:
// next.config.js module.exports = { cssModules: true, cssLoaderOptions: { modules: { exportLocalsConvention: 'camelCaseOnly', mode: 'pure' } } }
内容的提问来源于stack exchange,提问作者Wonay
相关产品推荐
相关产品推荐

