[LibSass非推奨化] node-sassとのお別れ ~ Dart Sassへ移行する


※ 当ページには【広告/PR】を含む場合があります。
2020/11/09
[Dart Sass対応] Sassを利用してカスタムカーソルを使ってみたお話




このほど唐突に
事実上のLibSassの開発断念 がアナウンスされ、コアな node-sass ユーザーにとってが悲しいニュースが飛び込んできました。
後髪を引かれる思いはしますが、仕方がないので公式で推奨されている
dart-sass cli をサクッと移行してみます。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】CSS/Sassをこれから学びたい人のためのオススメ書籍&教材特集

LibSass非推奨の経緯



Sassのコンパイラで圧倒的なシェアを誇っていた
node-sass だけに今回のLibSass非推奨の理由がなんとなく気になってきます。
公式のアナウンスを端的に掘り下げると、以下のような内容で説明されています。
長らくSassではLibSassを公式にサポートされているというポジションだったものの、この2年ほどLibSassの機能は更新されておらず、最近ではSassユーザーの意図としない問題が増加していたようです。
たとえば、ここ数年でも本家CSSなどは
min / max などの新しい機能が盛り込まれてきました。
LibSassにはその機能をサポートしていないため、それだけでも十分ユーザーにストレスを与えていたことでしょう。
また最近では新しいSassのモジュールシステムをサポートしていないため、LibSassが今後さらに時代遅れになってしまうことは火を見るより明らかな情勢になってきました。
公式がすべてのSassユーザーにLibSassから移行する必要があること示すことで、ユーザーに移行計画して対処して欲しいという警告のような意味合いを持たせるための処置のようです。
しかしながらLibSassのバグやセキュリティ問題の修正や最新nodeとの互換性などは定期的にメンテナンスを継続されるそうです。
SassのリソースをC++ APIを介して多言語に移植したり、高速コンパイルを実現する必要のある開発者はこれからもLibSassを選択することは可能です。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】CSS/Sassをこれから学びたい人のためのオススメ書籍&教材特集

node環境で移行する手順

Dart Sass のインストールの手順説明によるといくつかインストール方法があります。
ここではより簡単なのはnpmパッケージをグローバルインストールしてコマンドラインから叩けるようにする方法を試してみます。

            $ npm install -g sass

        

とこれだけで
Dart Sass Cli が導入されます。
インストールされた時の現状の手元のバーションは、

            $ sass --version
1.26.10 compiled with dart2js 2.8.4

        

ちなみに
Angular Cli 8.0以降 移行されています。
Sass単体を叩くことの少ない方は特にdart-sassの単独インストールを意識することは無いようです。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】CSS/Sassをこれから学びたい人のためのオススメ書籍&教材特集

@importから@useへ



node-sassから移行した場合、これまで作り込まれたアセットをコンパイルした時に大きく影響を受けるのが
@import の扱いだと思います。
すでに
@import は非推奨の用法であり、よりモダンに @use に置き換えることが求められます。
LibSass時代には制限されていた
@use を活用することで、node-sassユーザーにはいままで出来なかったことが色々と出来るようになります。
なお、大きなプロジェクト内のSassコードをまるごとアップグレードするのであれば、
コマンドラインから使える移行ユーティリティー を利用すると一括で移行できるようです。
もちろん
@import@use だけが移行のすべてではありませんが、折角なので 公式の@useガイド のサンプルを試してみます。

@use

@import@use は一見すると同じような作用があるように思えますが、仕組みは全く別物になります。
@importは外部のSassコードを宣言された位置に内容まるごと挿入してくれる、c言語でいうところのinclude的な役割だったのに対して、@useは外部のコードをカプセル化した一つのオブジェクトのように扱えるようです。
この作用をSassの
モジュール と呼んで区別しています。
ちなみに組込の
ビルドイン・モジュール というものがいくつかデフォルトで用意されているので、これも@useで呼び出すことで利用できます。
たとえばSassのプロジェクトでディレクトリ構造が以下のようになっているとすると、

            $ tree
.
├── style.scss
└── foundation
     ├── _code.scss
     └── _lists.scss

        

プロジェクトルートにある
style.scss は下位のフォルダのscssコードを以下のようにモジュールインポートが可能になります。

            @use 'foundation/code';
@use 'foundation/lists';

        

ここらへんは@import時代と変わりません。
@importはソースコードの任意の位置で呼び出しが可能だったのに対して、@useはファイルの冒頭で呼び出される必要がある点に注意してください。
foundation以下の
_code.scss および _lists.scss はcode要素とlist要素それぞれ付与したいスタイルを保持しているようなファイルだとして、

            code {
    padding: .25em;
    line-height: 0;
}

        
            ul, ol {
    text-align: left;

    & & {
        padding: {
        bottom: 0;
        left: 0;
        }
    }
}

        

のような内容になっています。
これをコンパイルしてみると、以下のcssコードに変換されます。

            code {
    padding: .25em;
    line-height: 0;
}
ul, ol {
    text-align: left;
}
ul ul, ol ol {
    padding-bottom: 0;
    padding-left: 0;
}

        

この結果は単なるcssの合成になりました。


モジュールのメンバを呼び出す



もっとモダンなSassらしいモジュールを用法をやってみます。
たとえば、モジュール内の変数を呼び出したい場合には
<名前空間名>.<変数名> 、関数は <名前空間名>.<関数名>() 、ミクスインだと @include <名前空間名>.<ミクスイン名>() 、となります。
ここでの
名前空間名 はScssのファイル名からプレフィックス( _ など)を抜いた文字列のことです。
今度はプロジェクト構造が以下になっているとすると、

            $ tree
.
├── style.scss
└── src
     └── _corners.scss

        

まず
_corners.scss には $radius という変数と rounded というミクスインが記述されているとすると、

            $radius: 3px;

@mixin rounded {
    border-radius: $radius;
}

        

これを
style.scss からモジュールとして呼び出し、そのメンバにアクセスする方法は以下のようになります。

            @use "src/corners";

.button {
    @include corners.rounded;
    padding: 5px + corners.$radius;
}

        

呼び出されたモジュールの名前空間名は
corners になり、変数は corners.$radius で、ミクスインは @include corners.rounded; で利用することができます。
またモジュールの名前空間名はエイリアス名やワイルドカードも利用できます。
エイリアス名を利用する場合には、

            @use "src/corners" as c;

.button {
    @include c.rounded;
    padding: 5px + c.$radius;
}

        

のように
as を使ってモジュールを修飾します。
このとき
as * にしてしまうことで、モジュールの中身全てを展開することも可能です。

            @use "src/corners" as *;

.button {
    @include rounded;
    padding: 5px + $radius;
}

        

この場合、ほぼ@importのような作用で複数のモジュールが呼び出されたら容易にメンバー名が衝突する問題に陥りやすく、あまり推奨される使い方ではないようです。

プライベートメンバー化



モジュール内のメンバをプライベートに設定し、アクセスを制限することも可能です。
やり方としては簡単で、モジュールのメンバ名で
$ に続く文字を -_ で始めればプライベートメンバにすることができます。
たとえば先程の
_corners.scss を以下のように変えてみます。

            $-radius: 3px;

@mixin rounded {
    border-radius: $-radius;
}

        

このとき
$-radius でプライベートに設定されます。
こうすると
style.scss から呼び出しても、

            @use "src/corners";

.button {
    @include corners.rounded;
    //👇$-radiusは外部から呼び出し禁止でコンパイルエラー
    padding: 5px + corners.$-radius;
}

        

となります。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】CSS/Sassをこれから学びたい人のためのオススメ書籍&教材特集

まとめ

node-sassからdart-sassへの簡単な移行 を試してみました。
個人的に複雑なSassライブラリなどのプロジェクトは持っていないので、
@import@use に変えるだけでほぼ移行完了でした。
それ自体は良いのですが、dart-nodeを取り入れることでSassの様々な最新機能がどっと利用可能になったので、これまで自作してきたライブラリの数々が用済みになって少し寂しい限りです。

参考サイト

LibSass is DeprecatedSassのモジュールシステムを@importから@useに移行する方法を考えてみた
記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】CSS/Sassをこれから学びたい人のためのオススメ書籍&教材特集