Migrator

The Sass migrator automatically updates your Sass files to help you move on to the latest and greatest version of the language. Each of its commands migrates a single feature, to give you as much control as possible over what you update and when.

UsageUsage permalink

To use the Sass migrator, tell itwhich migration you want to run and whatSass files you want to migrate:

sass-migrator <migration> <entrypoint.scss...>

By default, the migrator will only change files that you explicitly pass on thecommand line. Passing the--migrate-deps option tells the migrator to alsochange all the stylesheets that are loaded using the@use rule,@forward rule, or@import rule. And if you want to do a test run tosee what changes will be made without actually saving them, you can pass--dry-run--verbose (or-nv for short).

$cat style.scss$body-bg: #000;$body-color: #111;@import "bootstrap";@include media-breakpoint-up(sm) {  .navbar {    display: block;  }}$sass-migrator --migrate-deps module style.scss$cat style.scss@use "bootstrap" with (  $body-bg: #000,  $body-color: #111);@include bootstrap.media-breakpoint-up(sm) {  .navbar {    display: block;  }}

InstallationInstallation permalink

You can install the Sass migrator from most of the same places that you caninstallDart Sass:

StandaloneStandalone permalink

You can install the Sass migrator on Windows, Mac, or Linux by downloading thepackage for your operating systemfrom GitHub andadding it to yourPATH.

npmnpm permalink

If you use Node.js, you can also install the Sass migrator usingnpm by running

npm install -g sass-migrator

ChocolateyChocolatey permalink

If you usethe Chocolatey package manager for Windows, you can install theSass migrator by running

choco install sass-migrator

HomebrewHomebrew permalink

If you usethe Homebrew package manager for MacOS X, you can install DartSass by running

brew install sass/sass/migrator

Global OptionsGlobal Options permalink

These options are available for all migrators.

--migrate-deps–migrate-deps permalink

This option (abbreviated-d) tells the migrator to change not just thestylesheets that are explicitly passed on the command line, but also anystylesheets that they depend on using the@use rule,@forward rule,or@import rule.

$sass-migrator module--verbose style.scssMigrating style.scss$sass-migrator module--verbose --migrate-deps style.scssMigrating style.scssMigrating _theme.scssMigrating _fonts.scssMigrating _grid.scss

⚠️ Heads up!

Themodule migrator assumes that any stylesheet that is depended on usinga@use rule or a@forward rule has already been migrated to themodule system, so it won’t attempt to migrate them, even when the--migrate-deps option is passed.

--load-path–load-path permalink

This option (abbreviated-I) tells the migrator aload path where itshould look for stylesheets. It can be passed multiple times to provide multipleload paths. Earlier load paths will take precedence over later ones.

Dependencies loaded from load paths are assumed to be third-party libraries, sothe migrator will not migrate them even when the--migrate-deps option is passed.

--dry-run–dry-run permalink

This flag (abbreviated-n) tells the migrator not to save any changes todisk. It instead prints the list of files that it would have changed. This iscommonly paired with the--verbose option to print the contents of thechanges that would have been made as well.

$sass-migrator module --dry-run --migrate-deps style.scssDry run. Logging migrated files instead of overwriting...style.scss_theme.scss_fonts.scss_grid.scss

--no-unicode–no-unicode permalink

This flag tells the Sass migrator only to emitASCII characters to the terminalas part of error messages. By default, or if--unicode is passed, the migratorwill emit non-ASCII characters for these messages. This flag does not affect theCSS output.

$sass-migrator --no-unicode module style.scssline 1, column 9 of style.scss: Error: Could not find Sass file at 'typography'.  ,1 | @import "typography";  |         ^^^^^^^^^^^^  'Migration failed!$sass-migrator--unicode module style.scssline 1, column 9 of style.scss: Error: Could not find Sass file at 'typography'.  ╷1 │ @import "typography";  │         ^^^^^^^^^^^^  ╵Migration failed!

--verbose–verbose permalink

This flag (abbreviated-v) tells the migrator to print extra information tothe console. By default, it just prints the name of files that are changed, butwhen combined with the--dry-run option it also prints those files’ new contents.

$sass-migrator module--verbose --dry-run style.scssDry run. Logging migrated files instead of overwriting...<==> style.scss@use "bootstrap" with (  $body-bg: #000,  $body-color: #111);@include bootstrap.media-breakpoint-up(sm) {  .navbar {    display: block;  }}$sass-migrator module--verbose style.scssMigrating style.scss

MigrationsMigrations permalink

ColorColor permalink

This migration converts legacy color functions to the new color-space-compatible functions.

DivisionDivision permalink

This migration converts stylesheets that use/ as division to use thebuilt-inmath.div function instead.

--pessimistic–pessimistic permalink

By default, the migrator converts/ operations tomath.div even when itisn’t sure that it will be division when evaluated. It only leaves them as-iswhen it can statically determine that they’re doing something else (such as whenthere’s no SassScript involved, or when one of the operands is a string). Themath.div function currently functions identically to the/ operator, sothis is safe to do, but may result in new warnings if one of the arguments tomath.div at runtime is not a number.

If you want to avoid this behavior, you can pass the--pessimistic flag. Withthis flag, the migrator will only convert/ operations that it knows for sureare doing division. This will prevent any unnecessarymath.div conversions,but it’s likely to leave some division unmigrated if it can’t be statically determined.

ModuleModule permalink

This migration converts stylesheets that use the old@import rule to loaddependencies so that they use the Sass module system via the@use ruleinstead. It doesn’t just naïvely change@imports to@uses—it updatesstylesheets intelligently so that they keep working the same way they didbefore, including:

  • Adding namespaces to uses of members (variables, mixins, and functions) fromother modules.

  • Adding new@use rules to stylesheets that were using members withoutimporting them.

  • Converting overridden default variables towith clauses.

  • Automatically removing- and_ prefixes from members that are used fromother files (because otherwise they’d be consideredprivate and could onlybe used in the module they’re declared).

  • Convertingnested imports to use themeta.load-css() mixin instead.

⚠️ Heads up!

Because the module migrator may need to modify both member definitionsandmember names, it’s important to either run it with the--migrate-depsoption or ensure that you pass it all the stylesheets in your package or application.

$cat style.scss$body-bg: #000;$body-color: #111;@import "bootstrap";@include media-breakpoint-up(sm) {  .navbar {    display: block;  }}$sass-migrator --migrate-deps module style.scss$cat style.scss@use "bootstrap" with (  $body-bg: #000,  $body-color: #111);@include bootstrap.media-breakpoint-up(sm) {  .navbar {    display: block;  }}

Loading DependenciesLoading Dependencies permalink

The module migrator needs to be able to read all of the stylesheets depended onby the ones it’s migrating, even if the--migrate-deps option is notpassed. If the migrator fails to find a dependency, you’ll get an error.

$ls.style.scss  node_modules$sass-migrator module style.scssError: Could not find Sass file at 'dependency'.  ,1 | @import "dependency";  |         ^^^^^^^^^^^^  '  style.scss 1:9  root stylesheetMigration failed!$sass-migrator --load-path node_modules module style.scss

If you use aload path when compiling your stylesheets, make sure to passthat to the migrator using the--load-path option.

Unfortunately, the migrator does not support custom importers, but it does havebuilt-in support for resolving URLs starting with~ by searching innode_modules, similar towhat Webpack supports.

--remove-prefix–remove-prefix permalink

This option (abbreviated-p) takes an identifier prefix to remove from thebeginning of all variable, mixin, and function names when they’re migrated.Members that don’t start with this prefix will remain unchanged.

The@import rule put all top-level members in one global scope, so when itwas the standard way of loading stylesheets, everyone was incentivized to addprefixes to all their member names to avoid accidentally redefining some otherstylesheet’s. The module system solves this problem, so it’s useful toautomatically strip those old prefixes now that they’re unnecessary.

$cat style.scss@import "theme";@mixin app-inverted {  color: $app-bg-color;  background-color: $app-color;}$sass-migrator --migrate-deps module --remove-prefix=app- style.scss$cat style.scss@use "theme";@mixin inverted {  color: theme.$bg-color;  background-color: theme.$color;}

When you pass this option, the migrator will also generate animport-onlystylesheet thatforwards all the members with the prefix added back, topreserve backwards-compatibility for users who were importing the library.

This option may be passed multiple times, or with multiple values separated bycommas. Each prefix will be removed from any members that have it. If a membermatches multiple prefixes, the longest matching prefix will be removed.

--forward–forward permalink

This option tells the migrator which members to forward using the@forwardrule. It supports the following settings:

  • none (the default) doesn’t forward any members.

  • all forwards all members except those that started with- or_ in theoriginal stylesheet, since that was commonly used to mark a package-privatemember before the module system was introduced.

  • prefixed forwards only members that begin with the prefix passed to the--remove-prefix option. This option may only be used in conjunction withthe--remove-prefix option.

All files that are passed explicitly on the command line will forward membersthat are transitively loaded by those files using the@import rule. Filesloaded using the--migrate-deps option will not forward any new members.This option is particularly useful when migrating a Sass library, because itensures that users of that library will still be able to access all the membersit defines.

$cat _index.scss@import "theme";@import "typography";@import "components";$sass-migrator --migrate-deps module--forward=all style.scss$cat _index.scss@forward "theme";@forward "typography";@forward "components";

NamespaceNamespace permalink

This migration allows you to easily change thenamespaces of the@userules in a stylesheet. This is useful if the namespaces that the module migratorgenerates to resolve conflicts are non-ideal, or if you don’t want to use thedefault namespace that Sass determines based on the rule’s URL.

--rename–rename permalink

You can tell the migrator which namespace(s) you want it to change by passingexpressions to the--rename option.

These expressions are of the form<old-namespace> to <new-namespace> orurl <rule-url> to <new-namespace>. In these expressions,<old-namespace> and<rule-url> areregular expressions which match against the entirety of theexisting namespace or the@use rule’sURL, respectively.

For simple use cases, this just looks like--rename 'old to new', which wouldrename a@use rule with the namespaceold to instead benew.

However, you can also do this to accomplish more complicated renames. Forinstance, say that you previously had a stylesheet that looked like this:

@import'components/button/lib/mixins';@import'components/input/lib/mixins';@import'components/table/lib/mixins';// ...

Since all of these URLs would have the default namespacemixins when migratedto@use rules, the module migrator may end up generating something like this:

@use'components/button/lib/mixins'as button-lib-mixins;@use'components/input/lib/mixins'as input-lib-mixins;@use'components/table/lib/mixins'as table-lib-mixins;// ...

This is valid code since the namespaces don’t conflict, but they’re way morecomplicated than they need to be. The relevant part of theURL is the componentname, so we can use the namespace migrator to extract that part out.

If we run the namespace migrator with--rename 'url components/(\w+)/lib/mixins to \1', we’ll end up with:

@use'components/button/lib/mixins'as button;@use'components/input/lib/mixins'as input;@use'components/table/lib/mixins'as table;// ...

The rename script here says to find all of the@use rules whose URLs look likecomponents/(\w+)/lib/mixins (\w+ in a regular expression means to match anyword of one or more characters). The\1 in the output clause means tosubstitute in the contents of the first set of parentheses in the regularexpression (called agroup).

If you wish to apply multiple renames, you can pass the--rename optionmultiple times, or separate them with a semicolon or a line break. Only thefirst rename that applies to a given rule will be used, so you could passsomething like--rename 'a to b; b to a' to swap the namespacesa andb.

--force–force permalink

By default, if two or more@use rules have the same namespace after themigration, the migrator will fail, and no changes will be made.

In this case, you’ll usually want to adjust your--rename script to avoidcreating conflicts, but if you’d prefer to force the migration, you can insteadpass--force.

With--force, if any conflicts are encountered, the first@use rule willget its preferred namespace, while subsequent@use rules with the samepreferred namespace will instead have a numerical suffix added to them.