この記事は酔っ払いながら書いているので正しくない可能性があります。
Railsをwebpacker + PostCSSに移行してそれなりにコードを書いてみましたが、ちょっと思うところや考えなければいけないことがあったのでまとめてみます。
[Rails5.1.3] Asset Pipeline + SCSSからwebpacker + PostCSSに移行してみるか by 42 Design Work
PostCSSはとても面白い仕組みで、この仕組みを使っているだけでわくわくしてしまうようなものなのですが、組織で使うなら色々考えなければいけない部分もあるなと思います。
まず誰もが感じるのはこれだと思います。
PostCSSはプラグイン形式でいろいろな機能を追加していけるので、ビュッフェ感覚で気軽にプラグインを追加できてしまいます。
これはまさに秘伝のタレを作るようなもので、導入した本人はよくても、周りの人はそのルールを知ることが難しいですし、結局文法が分離してしまうリスクになってしまうと思います。
webpackerではPostCSSのプラグインとして、デフォルトで以下の2個が入っています。
これはまあいい落とし所だと思っていて、ギリギリ最低限のものに見えます。
webpack側のローダーにはsass-loaderがあるので、Railsから移行する上でスムーズにいけるように、と考えられているのだと思います。
が、cssnextはちょっとプラグインが過多で、いきなり全部把握するのはちょっと難しいです。 CSS4に準拠しているという意味ではまあ妥当なのでしょうが、個人的にいきなりcssnextを使うのはいいかなと思ったので使っていません。
というわけで、ここまで書いたようなことを感じたのもあって、先日書いた記事からPostCSSの構成をだいぶアップデートしました。
どういう考えでどういうアップデートをしたのかをまとめてみます。
とはいえcssnextは重要な指標になると思っていて、進むべき方向として参考にするには十分な存在だと思っています。 とても安易でもはや自分で判断したものではないのですが・・・。
cssnextは結局はプラグインの集まりなので、ここに使われているプラグインはある程度信用していいと思います。
CSS4の文法に則っていますし、もしプラグインが死んでも自分で作れる、あるいは誰かが作る可能性が高いと思います。
そもそも、Sassの機能を使いたいならPostCSSに移行すべきではありません。
これがとても大変でした。
変数なんてあちこちで使っていますし、記法が結構変な感じで変わるので置換もちょっと面倒で・・・。
これまでは
1$font-size: 1rem; 2.container { 3 font-size: $font-size; 4}
と書いていたのを、
1:root { 2 --font-size: 1rem; 3} 4 5.container { 6 font-size: var(--font-size); 7}
と書くようにします。ちなみにスコープが使えるようになります。私は使っていませんが。
追記: スコープは未実装でした。
置換したコマンドはちょっとどれだったか覚えていませんが、これでしょうか・・・。
1grep -rl "\\$" ./ | xargs perl -i -pe 's/\$([a-z|-]+)/var(--\1)/g'
動かなかったらすみません。
私はなぜかpostcss-nestedを使っていたのですが、postcss-nestingに切り替えました。
これによって以下が、
1.container { 2 .element { 3 font-size: 1rem; 4 } 5 6 .wrapper & { 7 padding: 1rem; 8 } 9}
こう書かなければいけなくなりました。
1.container { 2 & .element { 3 font-size: 1rem; 4 } 5 6 @nest .wrapper & { 7 padding: 1rem; 8 } 9}
これは置換する方法がわからなかったので、1個1個手で修正しました・・・。 まだCSSのファイルが40くらいだったので、軽い痛みで済みました。
なぜわざわざ大変な方に行ったのかと言うと、これもやはりCSS4の仕様に追従するためです。 中途半端にSassの機能を引きずりたくなかったので。
まあこれもSassで好きな機能だったのですが、やめました。 postcss-applyを使えばだいたい同じことができます。
こう書いていたものが、
1%filled { 2 background-color: #fff; 3 line-height: 1.25rem; 4} 5 6.container { 7 @extend %filled; 8}
こうなります。
1:root { 2 --filled { 3 background-color: #fff; 4 line-height: 1.25rem; 5 } 6} 7 8.container { 9 @apply --filled; 10}
カレントセレクタはどうなのでしょう、使えないと思います。
これはちょっとどうしようもありませんでした。
他に代替的な仕様がないのか探したのですが見つからなくて・・・。
最終的に、cssnextにないけど残したプラグインは以下の2個です。
これらは最悪やめるときがきても、grepで引っ掛けられるからいいかなと思います。
1plugins: 2 postcss-smart-import: {} 3 postcss-mixins: {} 4 postcss-apply: {} 5 postcss-nesting: {} 6 postcss-custom-media: {} 7 postcss-custom-properties: {} 8 postcss-hexrgba: {} 9 autoprefixer: {}
わからなくなったらplaygroundへ。
以上です。