如何通过Sass正确引入Bootstrap并实现跨文件变量共享?
问题描述
我有如下项目结构:
/resources /components component-a.js component-a.html component-a.scss /scss bootstrap.scss variables.scss my-app.js my-app.html my-app.scss
使用Aurelia框架与Webpack,Webpack的SCSS规则配置如下:
rules: [ ... { test: /\.scss$/i, use: [ 'style-loader', cssLoader, postcssLoader, sassLoader ] }, ... ]
bootstrap.scss按Bootstrap官方方式引入(暂用@import以保证正常运行):
// https://getbootstrap.com/docs/5.3/customize/sass/ // 1. Include functions first (so you can manipulate colors, SVGs, calc, etc) @import "bootstrap/scss/functions"; // 2. Include any default variable overrides here // 3. Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets) @import "bootstrap/scss/variables"; @import "bootstrap/scss/variables-dark"; // 4. Include any default map overrides here // 5. Include remainder of required parts @import "bootstrap/scss/maps"; @import "bootstrap/scss/mixins"; @import "bootstrap/scss/root"; // 6. Optionally include any other parts as needed @import "bootstrap/scss/utilities"; ... // 7. Optionally include utilities API last to generate classes based on the Sass map in `_utilities.scss` @import "bootstrap/scss/utilities/api"; // 8. Add additional custom code here
当前my-app.scss是第一个引入完整Bootstrap的文件:
@use 'sass:map'; @use './resources/scss/variables' as v; @use './resources/scss/bootstrap'; ...
现在需要在component-a.scss中访问Bootstrap的变量/混合宏,但直接@use './resources/scss/bootstrap'会导致Bootstrap代码被重复打包到CSS输出中,求解决办法。
解决方案
方法1:拆分Bootstrap引入,分离工具代码与样式输出
核心思路是把Bootstrap中不输出CSS的部分(变量、函数、混合宏)和会生成CSS的部分分开,组件只引入前者:
- 在
/resources/scss/下新建bootstrap-vars.scss,仅引入无CSS输出的Bootstrap模块:
// 仅引入不生成CSS的Bootstrap核心工具 @import "bootstrap/scss/functions"; @import "bootstrap/scss/variables"; @import "bootstrap/scss/variables-dark"; @import "bootstrap/scss/maps"; @import "bootstrap/scss/mixins";
- 修改原
bootstrap.scss,先引入bootstrap-vars,再引入生成CSS的部分:
@use './bootstrap-vars'; // 继续引入会生成CSS的模块 @import "bootstrap/scss/root"; @import "bootstrap/scss/utilities"; ... @import "bootstrap/scss/utilities/api"; // 自定义代码
- 在
component-a.scss中仅引入bootstrap-vars.scss,即可访问变量/混合宏,且不会重复输出CSS:
@use './resources/scss/bootstrap-vars' as bs; // 使用示例:引用Bootstrap变量 .example { color: bs.$primary; }
方法2:通过Webpack提取公共CSS chunk
利用Webpack的splitChunks配置,将Bootstrap这类公共CSS提取为单独的文件,避免重复打包:
修改Webpack配置的optimization部分:
optimization: { splitChunks: { cacheGroups: { styles: { name: 'styles', test: /\.css$/, chunks: 'all', enforce: true, }, bootstrap: { name: 'bootstrap', test: /bootstrap\/scss/, chunks: 'all', enforce: true, } } } }
这样Webpack会把Bootstrap的CSS单独打包成一个chunk,不管多少个组件引入,只会输出一次。
方法3:利用Sass模块的私有成员控制
如果不想拆分文件,可以在bootstrap.scss中将不需要对外暴露的样式部分标记为私有(前缀加-),仅推荐用于简单场景:
修改bootstrap.scss:
// 先引入无输出的工具代码 @import "bootstrap/scss/functions"; @import "bootstrap/scss/variables"; @import "bootstrap/scss/variables-dark"; @import "bootstrap/scss/maps"; @import "bootstrap/scss/mixins"; // 将生成CSS的部分包裹为私有模块 -@import "bootstrap/scss/root"; -@import "bootstrap/scss/utilities"; ... -@import "bootstrap/scss/utilities/api";
然后在组件中@use时,仅导入需要的变量/混合宏:
@use './resources/scss/bootstrap' as bs; .example { color: bs.$primary; }
内容的提问来源于stack exchange,提问作者Ivan Bacher
相关产品推荐
相关产品推荐

