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@import
s to@use
s—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 to
with
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 the
meta.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-deps
option 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@forward
rule. 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@use
rules 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.