1-4no diary

自作キーボード, CSS, その他好きなことなど

既存サービスにCSS設計(コンポーネント管理)を導入する方法

1からサービスを開発するときなら、1からCSS設計を行うことができますが、自社サービスの開発だとなかなかそんな状況には出くわしません。
既存サービスのぐちゃぐちゃなCSSに対して、開発をしていくことになります。
しかし、少しずつでもCSS設計を導入していきたいという場面があるかと思います。
既存CSSの依存を完全に断ち切れればいいのですが、そうはいかかないのではないでしょうか?
そんなとき、どのように設計(コンポーネント管理)を行うべきか、ということについてまとめていきます。

コンポーネント管理は可能な限り大きな単位で行いたい

この考え方の元進めてきます。
なるべく大きな単位で行っていた方が、いろいろなところで使用することができます。

よくある、一覧と詳細という単位で考えてみます。

一覧でAというコンポーネントを作ったとします。
一覧で何回か同じ見た目がでてくるので、これをコンポーネントAとしました。
そのため、list.component のようなディレクトリを作成し、この中に、_A.scss をおきました。
そして、 list 下に index.scss を作成して、この中で _A.scss を import しました。

今度は、詳細を考えていきます。

先ほどとは別の人が開発したとします。
そしてこのひとは詳細という中で、コンポーネント管理を行うことにしました。
そのため、detail.component のようなディレクトリを作成し、この中に、_B.scss をおきました。
そして、 detail 下に index.scss を作成して、この中で _B.scss を import しました。

結果以下のような構成になりました。

sass/
 ├ detail/
 │ ├ component
 │ │ └ _B.scss
 │ └ index.scss
 │
 ├ list/
 │ ├ component
 │ │ └ _A.scss
 │ └ index.scss

でもこのまま進むと、 detail と list は別々のまま進んでいきます。
もし detail で _A.scss を使用したくなったらどうしましょうか?

コンポーネントの呼び出し

そのまま detail.scss で _A.scss を import する。

この対応はどうでしょうか?
Sass的にも可能な方法です。でもこれはちょっと気持ちが悪くないでしょうか?
特に、_A.scss からしてみれば、list 以下のコンポーネントとして作成されているはずなのに、なぜか全然違う箇所から呼び出されています。

僕はこれは絶対にやって欲しくない方法です。混乱しか招きません。

sass 下に common 的なものを作る

下記のような構成に変更します。

sass/
 ├ common/
 │ └ _A.scss
 │
 ├ detail/
 │ ├ component
 │ │ └ _B.scss
 │ └ index.scss
 │
 ├ list/
 │ ├ component
 │ │ └ 移動
 │ └ index.scss

この後はいろいろな対応ができます。

 1. 必要なコンポーネントを各自で import する

毎回 import を追加したりしないといけないので、正直面倒です。
あまりオススメしません。

2. view 側で読み込むcssを増やす

これは common 下でも index.scss を作る必要があります。
common + 各ページ のCSSで1ページを構成することになります。

方針次第かなと思います。別に間違った方法ではないです。
レイアウト用の view ファイルで読み込んでおくというのいいと思います。

3. 各ページで import するためのファイルを用意する

1, 2 の組み合わせといった感じでしょうか。
全ての common を読み込むけど、css は1枚になります。
common 下に 一括 import 用のファイルを用意しておくと便利です。

今回の例では common が sass 直下に用意していますが、階層によってはもっと深いところに common が存在していることもあります。
大きなサービスだと、この状態になることが多いと思います。
そんなときはこの方法がオススメです。
詳細については後述します。

4. コンポーネントの枠を取っ払う

コンポーネントの管理を一括で行うということです。
各ページ単位では component ディレクトリを作成して切り出しません。
こうなっていれば、管理はとても簡単です。
ディレクターやデザイナーを巻き込んで対応した際の究極がここかもしれません。
コンポーネントが出揃えばページを作成する際に、ほとんどCSSを書く必要のないレベルが目指せます。
まぁ現実的にはここまでは厳しいです。


総合的に見て 3 がオススメです。
既存ページにも採用しやすいです。

ディレクトリについて

途中から採用する場合も、徐々に階層を上げていくことで、段階を踏んでリファクタが可能になります。
ただし、クラス名にプレフィックスをつけるなどの対応を取らないと、クラス名が衝突する可能性があるので注意が必要です。

徐々に階層を上げていくことで、最終的にはサイト全体に関わるものとなります。
最初から、わかっていればいいのですが、そういったことはなかなかありません。
なので、他に影響しない可能な限り大きな単位で、コンポーネント管理をしていくこをオススメします。
これが上記で 3 をオススメした理由です。

一番よくあるのは機能単位の開発だと思います。
そういったときは、その機能単位でコンポーネントを意識してCSS設計するだけでも、練習にもなるしスッキリすると思います。

ページ単位の場合、例に上げたような状況に出くわすこともあります。
そんなときは、なるべくいい方法で対応しましょう。
最初に作成した人がCSS設計を心がけていても、その後の対応次第ではぐちゃぐちゃになってしまいます。

まとめ

以上が、既存サービスにCSS設計(コンポーネント管理)を導入する方法になります。
チームで開発をする際は、一人で進めても間違った対応が入ってしまうと結局破綻するので、チームでルールを決めておく必要があります。
コンポーネント化ができないメンバーがいたとしても、設計を破綻させないようにルールだけは守れるようにしておきましょう。
import や view からの読み込みルールだけでも守れれば、破綻に向かうことはかなり軽減されるはずです。