TL;DR: Sass Migration in a Nutshell
Still using @import
in your SCSS? Time to level up. Here’s what I did:
✅ Replaced @import
with @use
'styles/...' as *
🛠️ Added r*esolving Sass Paths* for cleaner imports
🧪 Verified everything using npx sass-migrator — no issues found
🧹 Reordered CSS declarations above nested rules to remove deprecation warnings
📁 Renamed confusing css/ folder to styles/ for clarity
🧘♂️ Result: No more terminal spam, cleaner code, and a future-proof SCSS setup
When working on a growing frontend project using Next.js and Sass/SCSS, it’s easy to miss the warnings piling up in the console — until they become impossible to ignore.
Recently, I took on the task of cleaning up a Next.js codebase that was riddled with deprecated @import
usage and upcoming breaking changes related to how nested declarations behave. Here’s how I approached it, what I learned, and how you can apply it to your project.
🚨 Why Migrate from @import
?
💡 The
@import
rule is deprecated and will be removed in future versions of Sass. Use@use
or@forward
instead.
You may still see @import
sprinkled throughout your .scss files, and while it works for now, it comes with hidden costs:
- Unpredictable global scoping
- No clear module boundaries
- Duplicate style injection
- Tons of warnings in your terminal and browser console
In my case, the project had @import
'~css/colors' and similar statements all over .module.scss files. The tilde (~) was working magically, resolving to the src/ folder — although we never explicitly configured that (likely a leftover from legacy webpack behavior).
🔁 The @use
Syntax
The new module system introduced by Sass is smarter, safer, and designed to prevent namespace collisions. Here’s how I migrated:
✅ Before
@import '~css/colors';
@import '~css/vars';
@import '~css/mixins';
✅ After
@use 'styles/colors' as *;
@use 'styles/vars' as *;
@use 'styles/mixins' as *;
Along the way, I also renamed the folder from css/ to styles/ — it just makes more sense semantically and reads better for anyone joining the project.
🧭 Resolving Sass Paths in Next.js
To avoid long relative imports like ../../styles/colors, I initially configured the project like this:
// next.config.mjs
import path from 'path';
export default {
sassOptions: {
includePaths: [path.join(__dirname, 'src')],
},
};
This allowed me to write clean import statements such as:
@use 'styles/colors' as *;
✅ It worked.
⚠️ But there’s more you should know.
❗includePaths Is a Legacy Pattern
While includePaths is still supported by Dart Sass (and by the sassOptions field in Next.js), it’s not ideal for long-term use — especially with modern Sass modules.
💡 “The includePaths option is not recommended for use with
@use
. Instead, prefer using relative or package-based URLs.”
sass-lang.com/documentation/at-rules/use/#url
🧩 Better Path Resolution Options
✅ 1. Use Relative Paths (Recommended)
Instead of relying on global resolution, you can write:
@use '../../styles/colors' as *;
It’s a bit more verbose, but it’s:
- Explicit ✅
- Native to Sass ✅
- Portable across tools ✅
✅ 2. Use Webpack Aliases (Optional, with Caveats)
If you want clean, short import paths and you’re using Next.js with Webpack, you can configure an alias:
// next.config.mjs
import path from 'path';
export default {
webpack(config) {
config.resolve.alias['@styles'] = path.join(__dirname, 'src/styles');
return config;
}
};
Then in SCSS:
@use '@styles/colors' as *;
⚠️ Sass doesn’t know what
@styles
means unless your tooling resolves it (e.g. via sass-loader in Webpack).
✅ 3. Use the SASS_PATH Environment Variable
Define your base path globally using an environment variable.
In a .env file:
SASS_PATH=src
Then in your SCSS:
@use 'styles/colors' as *;
This works in Next.js and many other Sass toolchains, and is a nice middle ground between global includes and explicit paths.
✅ Built-in support
✅ Cleaner imports
⚠️ Slightly hidden magic
🛠 Using sass-migrator to Validate Migration
Sass provides a handy CLI tool to help you migrate - sass-migrator
Here’s what I ran:
npx sass-migrator module --migrate-deps -I ./src ./src/**/*.scss
# stdout
Nothing to migrate!
Which meant my manual changes were already valid under the module system — a good sanity check after a global find-and-replace in VSCode.
🔃 Fixing Declaration Order in Nested Rules
Another warning that was spamming my console came from how some SCSS blocks had declarations after nested selectors. Sass is aligning more with CSS behavior here.
📚 More info here: https://sass-lang.com/documentation/breaking-changes/mixed-decls/
The fix? Move all property declarations above nested selectors.
⚠️ Deprecated Style
.fee {
display: flex;
align-items: center;
&Text {
color: var(--txt2);
}
gap: 6px;
}
✅ Fixed Style
.fee {
display: flex;
align-items: center;
gap: 6px;
&Text {
color: var(--txt2);
}
}
🧹 Final Thoughts
This was a small but meaningful refactor that:
- Removed console spam
- Future-proofed our stylesheets
- Improved module clarity
- Made onboarding easier
If you’re using Sass in 2025, migrating to @use
isn’t just a nice-to-have If you’re maintaining a similar setup in Next.js. I highly recommend doing this migration sooner than later. It took me a couple of commits.
Top comments (0)