Search code examples
twitter-bootstrapsass

Importing Bootstrap into my SCSS via @use instead of @import causes problems


My project extends Bootstrap's responsive breakpoints. Here is the entrypoint SCSS file that was working for me:

@import "~bootstrap/scss/functions";
@import "~bootstrap/scss/variables";

$magnetar-grid-breakpoints : (
    1440: 1440px,
    1600: 1600px,
    1920: 1920px,
    2560: 2560px
);
$grid-breakpoints : map-merge($grid-breakpoints, $magnetar-grid-breakpoints);

$magnetar-container-max-widths : ();

@each $key, $val in $magnetar-grid-breakpoints {
    $magnetar-container-max-widths : map-merge($magnetar-container-max-widths, ($key : 0.95 * $val));
}

$container-max-widths : map-merge($container-max-widths, $magnetar-container-max-widths);

@import "~bootstrap/scss/bootstrap";

I'm just getting started on this project, and already I can tell that having to prefix all my variables (and mixins and functions) with "magnetar-" in order not to have conflicts with Bootstrap will get old fast. Therefore I thought I'd give the new Sass modules system a try and use @use instead of @import. Here is the rewritten SCSS:

@use "~bootstrap/scss/functions" as bootstrap_func;
@use "~bootstrap/scss/variables" as bootstrap_var;
@use "sass:map";

$grid-breakpoints : (
    1440: 1440px,
    1600: 1600px,
    1920: 1920px,
    2560: 2560px
);
bootstrap_var.$grid-breakpoints : map.merge(bootstrap_var.$grid-breakpoints, $grid-breakpoints);

$container-max-widths : ();

@each $key, $val in $grid-breakpoints {
    $container-max-widths : map.merge($container-max-widths, ($key : 0.95 * $val));
}

bootstrap_var.$container-max-widths : map.merge(bootstrap_var.$container-max-widths, $container-max-widths);

@use "~bootstrap/scss/bootstrap";

But the above compiles with this error:

SassError: @use rules must be written before any other rules.

It's referring to the last line. So I thought I'd try changing that line back to @import. That resulted in this error:

SassError: $color: theme-color("primary") is not a color.
    ╷
174 │ $link-hover-color:                        darken($link-color, 15%) !default;
    │                                           ^^^^^^^^^^^^^^^^^^^^^^^^
    ╵
  node_modules\bootstrap\scss\_variables.scss 174:43  @use

I'm lost as to what this means. Any ideas?


Solution

  • Here is the blog post about the new SASS module system. This mentions the following:

    In addition to namespacing, there are a few important differences between @use and @import:

    • @use only executes a stylesheet and includes its CSS once, no matter how many times that stylesheet is used.
    • @use only makes names available in the current stylesheet, as opposed to globally.
    • Members whose names begin with - or _ are private to the current stylesheet with @use.
    • If a stylesheet includes @extend, that extension is only applied to stylesheets it imports, not stylesheets that import it.

    The bold statement is why it doesn't work with the @use directive. All imported functions are not available globally, meaning the file ~bootstrap/scss/variables does not know about the functions declared in ~bootstrap/scss/functions.

    I honestly have no idea how to fix this though...