1クール続けるブログ

とりあえず1クール続けるエンジニアの備忘録

Sassもさらっと学んだ

いつもはDockerやKubernetesとべったりなのですが、最近はWEBフロントエンド+サーバサイドの開発をやっています。
サーバサイドは新卒で入った会社から慣れ親しみがありましたが、その会社のクライアントサイドがWindowsのデスクトップアプリ(※)だったため、WEBフロントエンドは未経験でした。
※ ちなみにWPFやUWPではなく、WinForms でした

昨今、cssメタ言語はWEBフロントエンド開発には欠かせないと聞きました。Vue.jsで対話的にテンプレートとか作成するときにも「Sass使う?それともStylus?」なんて聞かれた覚えがあります。
Stylusの方がパット見好みっぽいですが、会社で使っているのはSassなので勉強することにします。すでに軽く学んで実装とかも行っているんですが、学びなおしてリファクタに活かしたいというお気持ちです。

Sassにはいくつか種類がある

風の噂でSassはRubyが無いと動かせないという話を聞いていたのですが、それは全くの間違いで、むしろ2019年3月26日をもってサポートを終了していました。主な理由としてあげられているのは、要求されるパフォーマンスにRubyでの実装が追いつかなかったことのようです。また、Node.jsがフロントエンドの主流になっていったことも理由の一つとして挙げられています。

サポートされているのは以下の2つ

  • DartSass
  • LibSass

DartSassは現在のメイン実装で、最も早く新しい機能が追加されます。
Dartに書き換える理由は Sass: Announcing Dart Sass にて記載があります。少し掻い摘まみます。

RubySassは遅くRubyユーザ以外にはインストールが面倒であるものの機能追加が簡単、対してLibSassは速くて移植性が高いものの機能追加が難しいといった特徴を持っていました。2つは補完関係にあったが、どちらのソリューションも必要とされるほど良いものではなかったそうです。
Dartを選んだのは、高速かつ作業が簡単であったこと、JavaScriptとの互換性があるため既存のツールやビルドシステムにJS版を取り入れることができるという点だそうです(作者がDartチームだったことも大きそう)。

Sassの環境構築

webpackで1つのjsファイルにバンドルするケース
初めてwebpackを直接触った気がします、以前にAngularとかちょろっと触ったときには設定ファイルが自動生成されて、直接書き換えたことはなかったためです。
webpack自体は、英語のドキュメントを読み解けなかったので、こちらで勉強しました。

参考

webpack.js.org

$ npm init
$ npm install sass-loader style-loader css-loader sass webpack webpack-cli fibers --save-dev
$ mkdir -p src/js
$ mkdir src/scss
$ code webpack.config.js
$ webpack --mode development --watch   # 変更をウォッチ
const path = require('path');

module.exports = {
    mode: 'development',
    entry: './src/js/app.js',
    output: {
        filename: 'bundle.js',
        path: path.join(__dirname, 'dist')
    },
    module: {
        rules: [{
            test: /\.s[ac]ss$/i,
            use: [
                // Creates `style` nodes from JS strings
                'style-loader',
                // Translates CSS into CommonJS
                'css-loader',
                // Compiles Sass to CSS
                'sass-loader',
            ],
        }, ],
    },
};

Sassの構文

Sassの構文紹介の記事って日本語でもかなり落ちているんですが、パパっと観ていった中で一番分かりやすいのが公式のこのページでした。 分かりやすさとは関係ないけど、ページが軽量なのと広告無いのが地味に大きいんですかね。

sass-lang.com

ここでSCSSをトランスパイルした結果を観ることができる

www.sassmeister.com

変数 / ネスト

変数は$var: hogeの形で宣言することができ、利用するときにも$varで利用できる。
HTMLと同じように階層的にスタイルを書くことができる。ネストは深すぎると視認性を損なうため、3階層がまで良いようです。

I suggest you to not go more than 3 levels deep.

ベストプラクティスの記事 にありました。

$primary-color: #333;
$secondary-color: #fff;

nav {
  color: $primary-color;
  background-color: $secondary-color;
  
  li {
    width: 100%;
    
    &.primary-items {
      font-weight: bold;
    }
    
    // 隣接セレクタや兄弟セレクタも&を使って表現できる
    &+#selected {
      cursor: none;
    }
    
    // 疑似要素も然り
    &:hover {
      background-color: #666;
    }
  }
}

ファイルの分割

ソースコードの再利用性や保守性を高めるために、部分的にファイルを分けて、別のscssファイルからincludeすることができます。
そのincludeされる側のファイルをpartialというようにSassでは呼称しており、ファイル名の戦闘にアンダースコアが付きます。例えば、_partial.scssといった形です。そういったファイル名にすることによって、Sassはそのファイルをcssファイルにトランスパイルすべきでないことを知ります。

これらの仕組みは@useルールとともに利用することができ、Modulesと呼称されます。@useルールを使うことで、他のsassファイルをモジュールとしてロードすることができます。つまり、ロードしたファイルの変数や関数、mixinを参照することができます。
@useルールはDartSassにしか今のところ実装がなく、LibSassやRubySassの利用者を従来までの@importを利用する他なさそうです。@importは、下記の記事にあるように、名前空間が同一であったことから多くの問題を引き起こしたがために廃止する流れとなったとあり、DartSassを利用している人は@useを利用するべきのようです。@useの場合は、ファイル名.mixin名などのように利用しますが、@importはグローバル名前空間に共有されるので、簡潔な名前が使いづらい状態でした。

sass-lang.com

@extend

事前に定義したCSSプロパティのセットを複数のセレクタに共有することができるので、DRY原則の遵守に役立てることができる。
関連性のあるグルーピングに適用させるのがポイントで、そうしない場合に、下記のような負債を生み出してしまうので注意。ソースはこのブログextendという文字の通り継承させるものにのみ適用するのが良いということでしょう。ボタンなどが分かりやすい例と思っています。
関連性のないグルーピングに対してDRY原則を適用させたい場合には、引数なしの@mixinを利用するのが良さそうです。

@extendを使ったことで、スタイルシートが倍以上のサイズになってしまったり、ソースの順序がめちゃくちゃになってしまったり、セレクタが4,095個に達してしまったりしたケースをたくさん目にしてきました

f:id:jrywm121:20200518011649p:plain

@mixin

関数に近い機能を持ちます。下記のようにベンダープレフィックスなどが必要になるものに関してはかなり有効のようです。

@mixin transform($property) {
  -webkit-transform: $property;
  -ms-transform: $property;
  transform: $property;
}
.box { @include transform(rotate(30deg)); }

まとめ

@extendのネガティブな面について調べるまで想像することが出来ていませんでした。
保守性の高いコードを書くためにも、命名方法論のBEMなど周辺知識も合わせてしっかり勉強していこうと思います。
とりあえずリファクタですね。プロパティの順番などもある程度基準があるようなので合わせていきたいと思います。

余談ですけど、VSCodeでWEBサーバ簡単に建てられるんですね。Live ServerっていうExtensionであっさり出来すぎて笑っちゃいました。