CSS in ERB in JS という実証実験
2018-05-18 Fri.
はじめに
この内容は meguro.css#1 での発表を元に内容を整理したものです。
リポジトリ: euxn23/css-in-erb-in-js-poc
スライド: slideshare
動機
大規模な CSS つらい
- BEM/SMACCS/OOCSS は命名規則で管理しようと言っているけど……
- 大規模になってきたときに保守できなくなってくる
- 名前がかぶったり、typo があったり
- 命名規則ベースでがんばっても結局はグローバルに展開されている
- 読み込む css ファイルがどれかとかを命名規則だけで運用していくのは厳しい
- View 側との依存関係が非明示的になる
- 命名規則に属せられないスタイルが発生して、common とかになっていき……
- JS で動的にスタイルをいじる時に実装との依存が非明示になる
- JS で変更することをコメントで残すようになる
- JS の負債化が進んでいるとそこに巻き込まれる
CSS in JS という成功事例
- CSS in JS のメリット
- JS と CSS での変数共有とか動的な処理の見通しがよくなる
- CSS のスコープ制御を JS の module ベースでできる
- 使用するスタイルは import するので依存関係が明示化される
- 実質的に Single Page Application じゃないと使えない
- 既存の Rails や Laravel で使おうとすると設計レベルで作り直しになる
実証実験
CSS in Ruby の検討
- テンプレートで css を注入できる?
- これはできる
- Ruby 側で依存関係を明示できる?
- Rails は自動で require される
- = 明示化できない
- => スコープ管理が崩壊
- CSS in Ruby の補完が効かない
- 動的に CSS 操作できない
CSS in ERB in JS の検討
- JS で css を注入
- JS で module 化
- 両方とも CSS in JS と同様のアプローチで実現できそう
CSS in ERB in JS の実証実験
erb build script
index.html.erb.js
common-border.js
index.html.erb (生成後ファイル)
考察
功績
- 概ね CSS in JS と同様の手法で実装できる
- Template Literal 内で html / css(js) の補完が動作する
- css の依存を module で管理できる
- 動的な処理と css 宣言を集約できうる
- CSS in JS で行うような変数共有はできない
- グローバル変数を使えばできなくはないが悪手か
懸念点
- ERB / Rails 変数の補完が効かない
- IDE 向けプラグインを書けば解決すると思われる
- ビルドフローの検討
- Webpacker があることもあり、 Webpack で実行するのが自然か
- 変わり種だと akameco/s2s の検討も
- 出力前/後のどちらのインデントに合わせるか
- そもそも Rails の出力ソースのインデントは大概崩れているが
- ビルドフローで webpack loader をうまいこと作ればどうにかなりそうではある
- prettier での整形も検討
Slim => ERB 事前コンパイルのニーズ
- 新しい Ruby で ERB の実行速度が数倍に速くなったこともあり、事前に slim を erb にコンパイルしたいという考え
- このビルドフローを予め in JS 可能な形で作ってしまえば、今後普及させられる可能性
- slm.js 等、slim template を JS で使用するライブラリをうまく使えば、 slim 限定とはなるが簡略化できる可能性
はしがき
- 本実験の PHP での使用
- JS の Template Literal は
$
を使うが、 PHP も$
を使うため問題は生じないか - PHP の方が Template Literal 内での補完が期待できるのでは
- PHP 界隈での CSS 事情に詳しくないため、詳しい方の情報があればご意見ください
- JS の Template Literal は
Other Works
2024-05-11 Sat.
Powerfully Typed TypeScript
- TSKaigi 2024
2024-05-10 Fri.
pnpm の node_modules を探検して理解しよう
- ドワンゴ教育サービス開発者ブログ
2024-03-17 Sun.
neverthrow で局所的に Result 型を使い、 try-catch より安全に記述する
- Zenn
2023-12-20 Wed.
レガシーブラウザ向けのビルドオプションを剪定する
- ドワンゴ教育サービス開発者ブログ
2023-05-26 Fri.
Next.js で dynamic import を使い Client だけで動かす Component を実現する
- Zenn
2023-05-02 Tue.
Node.js でファイル名から拡張子を取り除く/取り出すために path.parse を使う
- Zenn
2023-02-27 Mon.
WSL2 で外部からアクセス可能にするために bridge mode を有効にする
- Zenn
2023-01-26 Thu.
init.vim & dein から init.lua & lazy.nvim へ、シンプル設定で移行した
- Zenn
2023-01-13 Fri.
kindle の本をブクログ形式の csv でエクスポートする@2023初春
- Zenn
2023-01-10 Tue.
自宅サーバの移設に際して docker から nerdctl に移行した
- Zenn
2023-01-10 Tue.
自宅サーバを rootless に移行した際のトラブル対応
- Zenn
2021-11-11 Thu.
並列実行した Promise で throw されても全てハンドルしたいときの方法(allSettled, finally, etc...)
- Zenn