AtomicDesign と

汎用UIコンポーネント集の両立

READYFOR株式会社

江面陽一 @neripark

江面陽一 a.k.a ねり

READYFOR株式会社

フロントエンド+Rails

@neripark

[use] React, TypeScript

[like] Vue.js, Nuxt.js, Netlify

[hobby] 音楽鑑賞、バンド活動、猫(cat)

SIer → Web制作を経て現職

お話すること

  • ​READYFORのフロントエンドアーキテクチャ紹介

  • 先日のリニューアルで新しく取り入れた2つの思想とそれらの両立(メイン)

    • AtomicDesign

    • 汎用UIコンポーネント集の実現

  • どうだったか

READYFORのアーキテクチャ

  • ​Ruby on Rails製のモノリシックなWebアプリケーション

  • フロントエンドは部分的にReact。2年ほど前から入っていた

    • "ReactOnRails" というGemを使って、RailsのViewファイル上に宣言的にコンポーネントを記述

    • CSR/SSRがパラメータ1つで切り替えられる

  • 継ぎ足された機能追加・改修による負債

    • フロント/サーバーの分離プロジェクト進行中

こんな感じです

# Gemfile
gem "react_on_rails", "11.3.0"
// package.json
{
  "dependencies": {
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-on-rails": "^11.3.0"
  }
}
# config/initializers/react_on_rails.rb
ReactOnRails.configure do |config|
  config.webpack_generated_files = %w[ app-bundle.js app-bundle.css prerender-bundle.js ]
  config.server_bundle_js_file = "prerender-bundle.js"
end
// client/react-client/src/client.js
import ReactOnRails from 'react-on-rails';
import TopPageTemplate from '../../../templates/TopPageTemplate'; //コンポーネントのファイル
import HogehogeTemplate from '../../../templates/HogehogeTemplate'; //コンポーネントのファイル

ReactOnRails.register({
  TopPageTemplate,
  HogehogeTemplate
});

// このファイルをwebpackのエントリーポイントとする。
# app/views/index/index.html.slim
div.container
  = react_component("TopPageTemplate", props: hogehoge, prerender: true)

やったぜ

先日のリニューアルで新しく取り入れた思想と、それらの両立

  1. AtomicDesignを用いたコンポーネント設計

  2. 汎用UIコンポーネント集の実現

新しいチャレンジ🙌

そもそも今回のリニューアルプロジェクトは...

  • CI刷新という全社的に大切な背景を持ったプロジェクト

    • 絶対的な期限という、守りの側面

  • 今後のフロントエンド開発の礎としたかった

    • 爆速で開発を進められるようにするための第一歩という、攻めの側面

(1) AtomicDesignを用いたコンポーネント設計

UIを粒度別に分類することで、

再利用しやすいUIを作るための設計手法

(1) AtomicDesignを用いたコンポーネント設計

  • 堅牢な設計手法がほしかった

    • 書籍や事例がたくさんあり、よい点を活かせそう

  • 課題となりそうな事項は最初にコミュニケーションをとってつぶしておいた

    • MoleculesとOrganismsの区別

      • 再利用するものはMolecules、しないものはOrganismsと決めた(伏線)

      • 色の名前、影の付き方なども切り出して定義

実際に少しご覧ください

(2) 汎用UIコンポーネント集の実現

  • 特集用の静的ページや提携企業様専用ページなど、リポジトリが別のページやアプリケーションが存在している

    • 将来増やしていく可能性もある

  • 今後、そちらも新UIにしていきたい

  • npmモジュール化して公開し、`npm install` で各アプリケーションで使えるようにしよう!(伏線)
    • `readyfor-elements` と命名
// package.json
{
  "dependencies": {
    "@readyfor/readyfor-elements": "^1.0.0"
  }
}

汎用UIコンポーネント集を公開したい

AtomicDesignがよさそう

楽しそう

デザイナー

エンジニア

しかし

難しかった...

実際に開発が始まると

  • 漠然とした疑問 1

    • hrefがハードコードされている。よくない気がするけどなぜかはわからない...

      • 動作はしっかりしている

// JSX

<SendMessage href={`/mypage/messages/path/to/hoge?id=${user.id}`}>
  <MessageIcon />
  <Text>
    メッセージを送る
  </Text>
</SendMessage>
  • 漠然とした疑問 2
    • このUI、繰り返し使うけど1ページでしか使われないんだよな...。別repoにするべきなんだろうか?

これらを解決する概念

Application-awareかどうか

Application-aware

  • ドメイン(+アプリケーション)固有の概念

    • 例:特定のページへ遷移するためのhref

    • 例:応援コメントの返信用コンポーネント
// JSX

<SendMessage href={`/mypage/messages/path/to/hoge?id=${user.id}`}>
  <MessageIcon />
  <Text>
    メッセージを送る
  </Text>
</SendMessage>

気が付かないまま実装がんばった

  • 一つの Application-aware な機能開発の際のRepoの往復がつらい...

    • 編集のソースは汎用コンポーネント集のほうにあるが、削除のソースは使う側にある、等
  • とはいえ、議論して根本から解決していく時間もない
  • 目先の課題も山積
    • ReactOnRails起因の問題や、IE用Polyfill等

無事、リスケなしで

リリース完遂🎉

反省点

  • 汎用UIコンポーネントには、Application-awareな実装を入れるべきではないという観点が抜けていた
  • 両者のパラダイムの違いを認識した上での議論が必要だった

    • AtomicDesign
      • デザイナーとの共通言語としての意味合い
      • 見た目をベースとした分け方
    • 汎用UIコンポーネント集
      • 実装面での生産性向上がメイン
      • Application-aware かそうでないかをベースにした分け方(にすべきだった)

まとめ

  • 良かった点

    • コンポーネント同士の責務の分離を考えて、実装に落とし込む基礎的な力がついたこと

      • style や イベントハンドラ

      • Props

    • プロジェクトをやりきれたこと

  • 今後は

    • 汎用UIコンポーネント集としてあるべき姿を議論し、Application-aware な部分をしっかり切り分けていく

ご清聴ありがとうございました!

Made with Slides.com