Angular 13中Sass嵌套导入第三方样式编译异常问题
问题:Angular 13嵌套SCSS导入导致部分样式未编译展开
环境背景
- Angular版本依赖:
"@angular/animations": "^13.3.12", "@angular/cdk": "^13.3.9", "@angular/common": "^13.3.12", "@angular/compiler": "^13.3.12", "@angular/core": "^13.3.12", "@angular/forms": "^13.3.12", "@angular/localize": "^13.3.12", "@angular/material": "^13.3.9", "@angular/platform-browser": "^13.3.12", "@angular/platform-browser-dynamic": "^13.3.12", "@angular/router": "^13.3.12",
- 历史正常环境:Angular 12 + webpack 以下版本 + node-sass,无此样式编译问题
样式文件结构
styles.scss
.d { @import "src/assets/scss/dashboard"; }
dashboard.scss
@import "~bootstrap/scss/bootstrap"; @import '~@fullcalendar/core/main.css'; @import '~@fullcalendar/daygrid/main.css'; @import '~@fullcalendar/timegrid/main.css'; @import '~@fullcalendar/list/main.css'; @import '~@fullcalendar/bootstrap/main.css'; @import '~@syncfusion/ej2-base/styles/material.css'; @import '~@syncfusion/ej2-buttons/styles/material.css'; @import '~@syncfusion/ej2-inputs/styles/material.css'; @import '~@syncfusion/ej2-popups/styles/material.css'; @import '~@syncfusion/ej2-lists/styles/material.css'; @import '~@syncfusion/ej2-splitbuttons/styles/material.css'; @import '~@syncfusion/ej2-calendars/styles/material.css'; @import '~@syncfusion/ej2-angular-calendars/styles/material.css';
问题现象
升级到Angular 13后编译完成:
- Bootstrap样式正常被编译展开到
.d选择器内 - FullCalendar和Syncfusion的CSS文件仍以
@import语句保留在.d选择器中,未被编译合并 - 将
dashboard.scss内容移到styles.scss顶层(脱离.d选择器)时,所有样式均能正常编译展开
解决方案
原因解析
Angular 13默认切换到webpack 5,同时用dart-sass替代了node-sass。两者对嵌套选择器内的@import处理逻辑不同:
- 对于
.scss后缀的文件,嵌套内的@import会被编译展开 - 对于
.css后缀的文件,嵌套内的@import会被保留为原生CSS导入,不会被编译合并
FullCalendar和Syncfusion的导入均为.css后缀,而Bootstrap是.scss后缀,因此出现差异。
具体解决方法
改用SCSS源文件导入
检查FullCalendar和Syncfusion是否提供SCSS格式的样式文件,将导入后缀改为.scss(或直接省略后缀,部分库支持自动识别):// dashboard.scss中修改FullCalendar导入 @import '~@fullcalendar/core/main'; @import '~@fullcalendar/daygrid/main'; // ... 其他FullCalendar导入同理 // Syncfusion导入修改 @import '~@syncfusion/ej2-base/styles/material'; // ... 其他Syncfusion导入同理拆分导入层级
将CSS文件的导入移到顶层,仅在嵌套选择器内导入SCSS文件:// styles.scss // 顶层导入所有CSS文件 @import "src/assets/scss/dashboard-css"; .d { @import "src/assets/scss/dashboard-scss"; }// dashboard-css.scss @import '~@fullcalendar/core/main.css'; @import '~@fullcalendar/daygrid/main.css'; // ... 其他FullCalendar和Syncfusion的CSS导入// dashboard-scss.scss @import "~bootstrap/scss/bootstrap"; // ... 其他需要嵌套的SCSS样式使用
@use替代@import(推荐)
dart-sass官方推荐用@use替代@import,模块化处理样式导入,避免嵌套导入的兼容性问题:// dashboard.scss @use "~bootstrap/scss/bootstrap"; @use '~@fullcalendar/core/main.css' as fc; // ... 按需引用样式强制将CSS文件当作SCSS处理
通过自定义webpack配置(Angular可修改angular.json引入自定义配置),添加规则将.css文件用sass-loader处理:module.exports = { module: { rules: [ { test: /\.css$/, use: ['sass-loader'], enforce: 'pre' } ] } };注:此方法可能引发兼容性问题,需充分测试。
内容的提问来源于stack exchange,提问作者Sammaye
相关产品推荐
相关产品推荐

