【Sass】@importの廃止に伴い@useと@forwardに書き換える


はじめに

新しいもモジュールシステム導入で@use, @forwardが追加され@importが2022年10月1日に廃止予定です。それに伴い行った置き換え作業を残しておきたいと思います。

https://github.com/sass/sass/blob/main/accepted/module-system.md#timeline

廃止に至った理由

さまざまな障害が発生しており、それらを解決するべく新しいモジュールシステム導入に至った。

https://sass-lang.com/blog/the-module-system-is-launched
  • It was next to impossible to figure out where a given variable, mixin, or function (collectively called “members”) was originally defined, since anything defined in one stylesheet was available to all stylesheets that were imported after it.
  • Even if you chose to explicitly import every stylesheet that defined members you used, you’d end up with duplicate CSS and strange side-effects, because stylesheets were reloaded from scratch every time they were imported.
  • It wasn’t safe to use terse and simple names because there was always a possibility that some other stylesheet elsewhere in your application would use the same name and mess up your logic. To be safe users had to manually add long, awkward namespaces to everything they defined.
  • Library authors had no way to ensure that their private helpers wouldn’t be accessed by downstream users, causing confusion and backwards-compatibility headaches.
  • The @extend rule could affect any selector anywhere in the stylesheet, not just those that its author explicitly chose to extend.

Sassについて

https://sass-lang.com/documentation#older-versions

SassにはDartSass、LibSass、RubySassと3種類存在するがLibSass、RubySassはすでに非推奨となっておりSass公式でDartSassを推奨している。@use@forwardも現在、DartSassだけがサポートしている。

@importを@useと@forwardに置き換える

実際に発生する置き換えパターンを4つ例にまとめてみる。(@import,@use,@forwardの詳細はドキュメントをご覧ください。)

パターン1: @importでscssファイルを読み込みスタイルをそのまま利用している

呼び出したスタイルをそのまま利用している場合は@import@useへ変更するだけでOK。

base.scss
body {
  margin: 0;
}
style.scss
- @import 'base';
+ @use 'base';

パターン2: @importで変数を読み込み利用している

@importでは呼び出した変数がグローバルとなりそのまま呼び出せるのに対し、@useを利用する場合は呼び出し元を指定する必要がある。@useではデフォルトでファイル名に応じた名前空間を持つためvariables.$変数名のように書く。

_variables.scss
$color-text: #333;
style.scss
- @import 'variables';
+ @use 'variables';

body {
- color: $color-text;
+ color: variables.$color-text;
}

補足

asを使うと独自に名前空間を定義することができる

style.scss
@use 'variables' as var;

body {
  color: var.$color-text;
}

パターン3: @importでmixinを読み込み利用している

パターン2同様に@useを利用する場合は呼び出し元を指定する。

mixin.scss
$bg-color: #efebef;

@mixin bg() {
  background-color: $bg-color;
}
style.scss
- @import 'mixin';
+ @use 'mixin';

body {
- @include bg();
+ @include mixin.bg();
}

パターン4: 複数scssファイルを一つのファイルに集約して読み込み利用している

@useでは呼び出したファイル内の要素のみ利用できる。そのため複数ファイルを集約したファイルを呼び出しても複数ファイル内の要素は参照できない。そのため@forward@useからの参照可能とする必要がある。

_variables.scss
$color-text: #333;
mixin.scss
$bg-color: #efebef;

@mixin bg() {
  background-color: $bg-color;
}
utils.scss
- @import 'variables'
+ @forward 'variables'
- @import 'mixin'
+ @forward 'mixin'
style.scss
- @import 'utils'
+ @use 'utils'
body {
  color: utils.$color-text;
  @include utils.bg();
}

実際に発生したエラー

Private members can't be accessed from outside their modules.

@useしてくるscssファイルの中で変数名に-または_をつけているprivate変数は呼び出すことができない。private変数を呼び出そうとするとエラーとなる。

SassError: Private members can't be accessed from outside their modules.116 │   color: variables.$--color-text;^^^^^^^^^^^^^^^^^^^^^^^^^^^
variables.scss
// NG
$--color-text: #333
// OK
$color-text: #333

Private members can't be accessed from outside their modules.

@useは他のルールよりも先に書かなくてはいけない。書き換えの過程で@importも存在している場合等、@useよりも前に@importがある状態だとエラーとなる。

SassError: @use rules must be written before any other rules.75 │ @use 'mixin';^^^^^^^^^^^^^^^^^^^^^^^^^^
// NG
@import 'variables'
@use 'mixin'

// OK
@use 'mixin'
@import 'variables'

さいごに

ドキュメントを読んでみてからと思っていたけど、コード例も多く載っているので実際に手を動かしながらの方が理解しやすかった印象です!