DEV Community

Cover image for From @import to @use: Migrating Sass the Right Way in a Next.js Project
vavilov2212
vavilov2212

Posted on

1

From @import to @use: Migrating Sass the Right Way in a Next.js Project

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.

sass-lang.com/documentation/breaking-changes/import/

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';
Enter fullscreen mode Exit fullscreen mode

✅ After

@use 'styles/colors' as *;
@use 'styles/vars' as *;
@use 'styles/mixins' as *;
Enter fullscreen mode Exit fullscreen mode

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')],
  },
};
Enter fullscreen mode Exit fullscreen mode

This allowed me to write clean import statements such as:

@use 'styles/colors' as *;
Enter fullscreen mode Exit fullscreen mode

✅ 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 *;
Enter fullscreen mode Exit fullscreen mode

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;
  }
};
Enter fullscreen mode Exit fullscreen mode

Then in SCSS:

@use '@styles/colors' as *;
Enter fullscreen mode Exit fullscreen mode

⚠️ 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
Enter fullscreen mode Exit fullscreen mode

Then in your SCSS:

@use 'styles/colors' as *;
Enter fullscreen mode Exit fullscreen mode

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

📚 node-sass on GitHub

🛠 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!
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

✅ Fixed Style

.fee {
  display: flex;
  align-items: center;
  gap: 6px;

  &Text {
    color: var(--txt2);
  }
}
Enter fullscreen mode Exit fullscreen mode

🧹 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.

Runner H image

Automate Your Workflow in Slack, Gmail, Notion & more

Runner H connects to your favorite tools and handles repetitive tasks for you. Save hours daily. Try it free while it’s in beta.

Try for Free

Top comments (0)

NextJS tools that help you ship faster

NextJS tools that help you ship faster

Skip boilerplate and focus on features. Kinde handles auth, access control, and billing behind the scenes.

Get a free account

👋 Kindness is contagious

Discover fresh viewpoints in this insightful post, supported by our vibrant DEV Community. Every developer’s experience matters—add your thoughts and help us grow together.

A simple “thank you” can uplift the author and spark new discussions—leave yours below!

On DEV, knowledge-sharing connects us and drives innovation. Found this useful? A quick note of appreciation makes a real impact.

Okay