Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing global variables in Sass with Webpack without multiple imports

I'm developing an application with React using Bootstrap 4 with Sass and webpack for building, every React component has it's own .scss file.

I've run into a problem, where I need to use Bootstrap's variables, but I can't import bootstrap because I end up with Bootstrap imported multiple times (apart from performance issues duplicate imports keep overriding my changes to Bootstrap's rules)

My main two problems are:

  1. ComponentA stylesheet has to access Bootstrap's variables and mixins (i.e. button-variant), to achieve that I have to @import Bootstrap inside my .scss file (otherwise I end up getting undefined variable errors).
  2. Adding @import '~bootstrap' to every component's stylesheet results in importing whole Bootstrap multiple times. So when I override a variable, i.e. $body-bg in my global.scss file, which contains shared styles, it only uses my value in first import, what means that every succeeding Bootstrap import doesn't get my variables, and keeps overriding it with defaults.

Are there any methods for dealing with that kind of problems? My guess would be to somehow enable "global scope", so I can use variables/mixins without continously importing whole Bootstrap.

Edit: I've found a workaround, when Sass files are imported from other Sass file, the variables are accessible, so creating a single big import.scss file instead of using separate imports from .js files seems to work.

like image 707
Selenir Avatar asked Nov 08 '22 13:11

Selenir


1 Answers

Had the same issue, managed to resolve it by creating a file bootstrap.imports.scss that imports my custom variables and the mixins, variables etc. from bootstrap:

@import 'bootstrap_variables'; // contains the custom bootstrap variables

@import '~bootstrap/scss/functions';
@import '~bootstrap/scss/variables';
@import '~bootstrap/scss/mixins';

Then in the webpack config I use the sass-resources-loader loader like this:

rules: [{
  test: /\.(scss)$/,
  loaders: ExtractTextPlugin.extract({
    fallback: 'style-loader', // in case the ExtractTextPlugin is disabled, inject CSS to <HEAD>
    use: [{
      loader: 'css-loader', // translates CSS into CommonJS modules
      options: {
        sourceMap: true
      }
    },
    {
      loader: 'postcss-loader', // Run post css actions
      options: {
        sourceMap: true,
        plugins: function () { // post css plugins, can be exported to postcss.config.js
          return [
            require('postcss-flexbugs-fixes'),
            require('autoprefixer')
          ];
        }
      }
    },
    {
      loader: 'sass-loader', // compiles SASS to CSS
      options: {
        sourceMap: true
      }
    },
    {
      loader: 'sass-resources-loader',
      options: {
        resources: [
          `${path}/bootstrap.imports.scss`
        ]
      },
    }]
  })
}]

With this, I am able to import a scss file anywhere and use the botostrap functions or variables

like image 123
Guillaume Avatar answered Nov 15 '22 05:11

Guillaume