scss px-removeとcalc optimizationのバグ
こんにちは。 Showcase Gigハブチーム所属のリョです。 最近frontend開発中におもしろいバグと出会って解決までの流れはブログとして残そうかと思ってます。
バグの説明
scssのバグだからscss fileに書いてた内容は:
margin: max(0px, calc((100vm - 1000px) / 2))
結局下のcssとして出力されました。
margin: max(0, 50vm - 500px)
まとめて言うと、三ヵ所変更されました。
0px -> 0に、pxの単位が外されました。
((100vm - 1000px) / 2) -> (50vm - 500px)に、裏で計算されて最適化(optimize)されました。
開発環境は問題なく、qa環境が上の通りになりました。
解決まで
最初
QA環境はproductionでcompileされるので、webpackの一部のpluginがそれを見てproduction向けの最適化をやっているのでは? と思ってまして、sass-loaderをいろいろ調べました。
1st try
このブログを見つけて、書いた通りmargin: unquote("max(0px, calc((100vm - 1000px) / 2))")に直してもだめです。
2nd try
sass-loaderはたしかに裏でsassを使っているので、sassをローカルでinstallしてsass index.scssコマンドで試したら正しく出力されましたmargin: max(0px, calc((100vm - 1000px) / 2))。ということはsass-loaderとは関係ないか。
次
sass-loaderをへてcss-loaderとstyle-loaderの処理終わったら、mini-css-extract-pluginを使ってcssを抽出して、外部ファイルとしてhtmlに埋めています。このcssファイルに間違ったstyleは出力されてます。
3rd try
sass-loaderとcss-loaderの出力をどう見るかはわからないですが、mini-css-extract-pluginを抜きにしてcssとjsをまとめてbundleしてみたところ。出力は正しいです! ということは犯人mini-css-extract-pluginですか? いろいろ調べてみました、このスレッド見つけました。mini-css-extract-pluginでもないか ?
4th try
いやとりあえずmini-css-extract-pluginを最新バージョンに更新して試しようとしましたが、webpackも5に更新しないとできないようです。webpack5への更新は結構時間かかるのでmini-css-extract-pluginの更新も諦めるしかない。
続き
今までたどり着いて案は2つしかないと思ってました。
max使わずscssを書き換える
mini-css-extract-pluginの代替のpluginに切り替える
5th try
css弱者かつ書き換えの心当たりがないので、代替できるpluginを探してみました。 結局良いものは見つからなかったですが、css-minimizer-webpack-plugin というpluginが見当たりました。extractよりminimizer pluginが最適化する可能性は高いだと思いながら、webpack設定ファイルを再び見たらやはり{optimization: new CssMinimizerPlugin()}のところで使われてますね。 (そうか、問題ない開発環境はもともとminimizer pluginを使っていた記憶が蘇りました) それを消してもう1回bundleして見たらcssは正しく出力されました!
最後
cssは直りましたが、cssファイルサイズは20KB強増えました。2つの案があります。
optimizationせずこのままにするか
何かの設定を入れてファイルサイズ膨らまないように修正するか 20KBは多いなと思ってもっと調べみまして、webpack pluginページ経由してcssnanoにたどり着けました。
計算最適化はこれか: calc
px-removeはこれか: convertValues 上の設定サイト通りoffしたら完璧に解決できました!
new CssMinimizerPlugin({
minimizerOptions: {
preset: [
"default",
{
calc: false,
convertValues: false,
},
],
}
}),
補足
途中でcssをmargin: max(0px, calc(100vm - 1000px) / 2)に書き換えてcalc optimzationの課題を解決しましたが、0px convertはcssnano設定を変えないと直らないです。
振り返り
最初からはcss-minimizer-webpack-pluginことを忘れて、style-loader, css-loader, sass-loaderの先入観で調べ始めまして、特に開発とQA環境のwebpackを細かく比べてなかったです。webpackは強いですが設定は複雑になってだんだん見比べたくなります。よって解決までは結構遠回りしました。 これによって先入観はよくないものとも思わないです。それを利用して早めにエラーを特定できるケースもあります。ケースバイケースですね。
仲間募集
Showcase Gigでは、一緒に働く仲間を探しています!
この記事ではエンジニア組織の文化を少しお見せしましたが、もっと知りたいという方は以下の採用ページを御覧ください!