Modern Sass Architecture with @use and Built‑in Modules
Learn how Sass’s @use rule eliminates duplicate output and global namespace clashes by loading modules once under an explicit namespace, with a concrete migration example and verification steps.
15 Aug 2025, 18:09 UTC

The problem with @import in large Sass projects
When a stylesheet uses the legacy @import directive, Sass treats every import as a separate copy of the file. If the same partial is imported from multiple entry points, its CSS rules are emitted repeatedly, bloating the final output. Moreover, all variables, functions, and mixins become globally scoped, making it hard to trace where a particular name originates and increasing the risk of accidental overrides.
How @use solves duplication and namespace pollution
The @use rule, introduced in Dart Sass 1.23, loads a module once per compilation and makes its members available under an explicit namespace. Because the module is evaluated only once, any CSS it generates appears just once in the output, regardless of how many times it is referenced. Built‑in modules such as sass:color, sass:map, and sass:list provide namespaced functions (e.g., color.adjust()) that replace the old global counterparts.
Key mechanics
- Single evaluation: The module’s SCSS is parsed and executed one time.
- Explicit namespace: Members are accessed as
namespace.member(you can also assign a shorter alias withas *oras ns). - No duplicate CSS: Even if
@useappears in ten different files, the generated CSS from that module appears only once.
Worked example: migrating a button component
Suppose we have a button partial that previously relied on global color functions and a shared mixin file.
/* _buttons.scss (legacy version) */
@import "utils";
$brand-blue: #0066ff;
.btn-primary {
background-color: adjust-hue($brand-blue, 10);
@include button-base;
}
The utils.scss file contains a mixin and a few helper variables that are also imported elsewhere, leading to duplicated output.
We migrate to @use as follows:
/* _buttons.scss (new version) */
@use "sass:color";
@use "utils" as *; /* optional: expose members without a prefix */
$brand-blue: #0066ff;
.btn-primary {
background-color: color.adjust($brand-blue, $hue: 10);
@include button-base;
}
Explanation:
- The built‑in
sass:colormodule is loaded once and accessed via thecolor.namespace. - The
utilsmodule is also loaded once; we chose theas *shortcut to keep the existing mixin call unchanged, but you could also write@include utils.button-base. - If another file (e.g., a theme partial) also
@use "utils", Sass will not re‑evaluateutils.scssand its CSS will appear only once in the final stylesheet.
Compilation and verification
Run the migration with Dart Sass (≥1.23):
dart-sass src/styles.scss:dist/styles.css --style=compressed
To verify that duplication is eliminated, inspect the compiled CSS for the button‑base rules:
grep -c "button-base" dist/styles.css
The count should be 1 (or however many times the mixin actually generates rules, but not multiplied by the number of imports).
Additionally, you can confirm that no @import directives remain:
grep -r "@import" src/ # should return no matches
Trade‑offs and limitations
While @use brings clear benefits, there are practical considerations:
- Verbosity: Namespaced calls like
color.adjust($blue, $lightness: -10)are longer than the globaladjust-color($blue, -10). Teams often adopt a convention of short aliases (@use "sass:color" as c;) to keep readability. - Migration effort: Every
@importmust be replaced and all references to globals updated. Automated tools (e.g.,sass-migrator) can help, but manual review is still needed for mixins and functions that relied on implicit global scope. - Implementation support: Only Dart Sass provides full
@usesupport. Older LibSass versions (used in some Node‑sass environments) lack the feature, so ensure your build uses Dart Sass ≥1.23.
Actionable closing steps
- Upgrade to Dart Sass:
npm i -D sass(ensure version ≥1.23). - Run the official migrator on a copy of your codebase:
sass-migrator migrate --use **/*.scss. - Audit the output for any remaining
@importstatements and fix them manually. - Add a lint rule (e.g., stylelint-plugin-no-import-only) to forbid future
@importusage. - Verify the build: compile, check for duplicate CSS, and run your visual regression suite.
By adopting @use with explicit namespaces and leveraging Sass’s built‑in modules, you eliminate duplicate output, make dependencies transparent, and set a foundation for scalable, maintainable stylesheets.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.