npm-scriptsでdart-sass → postcssのタスクを作る。(ディレクトリ指定 & watch)
npm-scriptsで、ディレクトリ内のsassファイルを編集したらpostcssも自動で走らせて保存できるようにしたい。開発中に使うのでwatchもさせる。gulpやwebpackでやる方法もあるけど、今回はnpm-scriptsだけで。
ググると「特定のsassファイル単体を指定」する方法は見つかったが、アウトプットしたいファイルが増えるたびにいちいち記述を足すのは不便。ディレクトリ指定でおねがいします。
自分で工夫してとりあえず実現できたのでここに記す。
最終的にこう。
"scripts": {
"dev": "npm-run-all -s clean watch:sassToPostcss",
"clean": "rm -rf dist/* & rm -rf tmpCss/*",
"watch:sassToPostcss": "npm-run-all -s build:sass -p 'build:sass -- -w' 'build:postcss -- -w'",
"build:sass": "sass src/sass:tmpCss --no-source-map",
"build:postcss": "postcss tmpCss/*.css --dir=dist/css --no-map"
},
利用パッケージ
sass、postcss、postcss-cli、npm-run-all。
npm run dev
で開発開始。sassファイルを更新すると処理が走ってdist/に処理結果のcssが吐き出される。
cssファイルの一時経由先として「tmpCssディレクトリ」を設けてるのがコツ。
「watch:sassToPostcss」から連なる処理から解説
まず「build:sass」でsrc/sass/内の(.scss|.sass)を、tmpCss/へトランスパイル。次にwatchを効かせる為、追加オプション「-- -w」を足して「build:sass」「build:postcss」を実行。
「tmpCssディレクトリ」が必要だった理由
直でsassからdist/に吐き出したcssを、postcssの「--replace」で上書きできればシンプルだった…。しかし、いざ実行するとpostcssが「--replace を使うと、同時に --watchが出来ないよ!」と英語で怒ってくる。しぶしぶ経由ディレクトリを作成。
スタート時にwatch無しで一度処理させる理由
postcssは、処理時に目的のファイル(今回で言えば、tmpCss/に一つ以上のcssファイル)が無いと、エラーでコケてしまう。sassとpostcssの処理にwatchを効かせたものを、最初からnpm-run-allのパラレル処理「-p」で行おうとすると、sass側のトランスパイルが完了する前にpostcssが走り、やはりコケてしまう。
そこで、まずはnpm-run-allのシリアル処理「-s」で確実に、sassの処理を行い、ファイルの存在を確定させコケさせない。その後、改めてwatchをかける。
最後に
もっといい方法知りません?
--replace を使うと、同時に --watchが出来ない
こちら少し文脈を意識してデモを作ってみました。達成したいことに齟齬があるかは不明ですが。
以下でコメントアウトしている部分をコメントインするなどして生成されたCSSが変化していることが確認できました。
@each $item in $results {
$i: $i + 1;
.text-#{$i} {
--font-size-px: #{map-get($item, "font-size-px")};
--font-size-rem: #{map-get($item, "font-size-rem")};
--font-size-vw: #{map-get($item, "font-size-vw")};
font-size: var(--font-size-px);
@include mq("xl") {
// font-size: var(--font-size-vw);
}
}
}
demo code.
{
"scripts": {
"do": "ts-node-esm -r tsconfig-paths/register src/index.ts",
"dev": "npm-run-all -s do:sass do:postcss",
"do:sass": "sass --watch --no-source-map src/styles/sass:src/styles/css",
"do:postcss": "postcss --watch --no-map --replace src/css/**/*.css"
}
}
簡単ですが、以上です。