@useまたは@include meta.load-cssで読み込んでるscss(sass)ファイルを更新してもコンパイルされない問題解決


まずはじめに

本件はgulpを使ってscssまたはsassをコンパイルしてる人向けの記事です。
@use」などを使って依存関係にあるscss(sass)ファイルを更新してもコンパイルされないことを困っている人の助けになればと。

問題

@use」または「@include meta.load-css」にすると、gulp-cacheまたはgulp.lastRunを使ってキャッシュしてる場合に、そのファイルを更新してもBrowserSyncでwatchしててもコンパイルされない。

忙しい人のための結論

gulp-dependentsを使 って、正規表現を追加設定すれば解決できる。
「解決方法」よりgulpfileの記述を見てください。

そもそもなぜ「@import」から変えなければならないのか。

@importが2022年10月1日に廃止される予定。
Dart Sassを使うのが主流になりそうなので、node-sassからDart Sassへと移行しようとした。
@import」を「@use」または「@include meta.load-css」へと変換するのは、Sass-migratorを使えばさほど大変ではなかった。
※Sass-migratorの記事もググってもあまり出てこなかったので、これはこれで今度Qiitaにまとめたいと思う。

依存関係にあるファイルを更新してもコンパイルされない

普通にコマンド打ってscss(sass)をコンパイルする分には何も問題ない。
しかし、gulp-cacheまたはgulp.lastRunなどをつかってキャッシュを効かせていると、BrowserSyncなどでwatchしててもコンパイルされない問題が起きた。

そもそもこれは「@import」を使ってる時にも発生していたのだがgulp-progenyというパッケージを使えば解決ができた。
これが「@use」または「@include meta.load-css」にすると効かなくなるのであった。

なぜこのようなことが起きるのか

「gulp-progeny」を追ってみたのだが、どうやら依存してるprogenyがそもそも「@import」にしか対応してないからのようだった。
どうやって依存関係を調べてるのかっていうと正規表現で「@import」を頑張って探してるだけの模様。
同じようなパッケージであるsass-graphも同様だった。

どうやって解決しよう

調査してるとパッケージを自分で修正してしまう、という手段を取ってる人がいた。
それをパッケージを配布してる人にプルリクすればきっと取り込んでもらえるかもしれないけど、そうなるといつ解決できるかわからない。

別の方法を考えてみた。

gulp-dependentsに出会った

さらに調べていくとgulp-dependentsというパッケージが「@use」と「@forward」に対応してることを発見した。
これで解決だ!って思った。

しかし罠が待っていた。

@include meta.load-css」には対応してないのだ。

gulp-dependentsがここが優れていた

「gulp-dependents」は自分で設定を追加することができるのである。
なので、自分でさらに正規表現を追加すれば「@include meta.load-css」で読み込んでるファイルを編集してもコンパイルすることができる。

解決方法

長々と話したけれど、gulpfileを以下のようにすると良さそう。
scssファイル前提にしてるので、sassを使ってる人は「".scss"」になってる箇所を「".sass"」にしたら良いと思う。
(試してないのでわからない)
@include meta.load-css」を使ってなくて「@use」または「@forward」しか使ってない人は「const dependentsConfig」は不要。

※未だ非推奨のgulp.taskの書き方になっているのはご了承ください。

gulpfile.js
// require
const gulp = require('gulp');
const sass = require('gulp-sass')(require('sass'));
const cache = require('gulp-cached');
const dependents = require('gulp-dependents');

// output
const dest = './css/'

// sass task
gulp.task('sass', function(done){
  // gulp-dependents config
  const dependentsConfig = {
    ".scss": {
      parserSteps: [
          /(?:^|;|{|}|\*\/)\s*@(import|use|forward|include)\s+((?:"[^"]+"|'[^']+'|url\((?:"[^"]+"|'[^']+'|[^)]+)\)|meta\.load\-css\((?:"[^"]+"|'[^']+'|[^)]+)\))(?:\s*,\s*(?:"[^"]+"|'[^']+'|url\((?:"[^"]+"|'[^']+'|[^)]+)\)|meta\.load\-css\((?:"[^"]+"|'[^']+'|[^)]+)\)))*)(?=[^;]*;)/gm,
          /"([^"]+)"|'([^']+)'|url\((?:"([^"]+)"|'([^']+)'|([^)]+))\)|meta\.load\-css\((?:"([^"]+)"|'([^']+)'|([^)]+))\)/gm
      ],
      prefixes: ["_"],
      postfixes: [".scss", ".sass"],
      basePaths: []
    }
  };

  gulp.src(['./scss/**/*.scss'])
  .pipe(cache( 'sass' ))
  .pipe(dependents(dependentsConfig))
  .pipe(sass.sync({outputStyle: 'expanded'}).on('error', sass.logError))
  .pipe(gulp.dest(dest));

  done();
});

const dependentsConfigに書いてる「parserSteps」でめっちゃ正規表現を頑張ってる感じ。
この辺りの説明はgulp-dependentsConfigurationに書かれてるので、そちらを読んでください。
※翻訳がめんどくさかった

終わりに

この辺り、ググっても日本語の記事ってなかなか出てこなったので、もし同じように困っている人の助けになったら幸いです。

参考