Reactでのフロントエンド開発の業務に携わって1年が経ったので振り返る
はじめに
この記事はGMOメディア株式会社 Advent Calendar 2024の19日目の記事です。
新規プロダクトのフロントエンドの技術選定でReact/Next.js(AppRouter)を採用し、開発しはじめてから約1年が経過しました。
もともと社内の既存のプロダクトはJavaScriptをゴリゴリに書くものが少ないこともあり、テンプレートエンジンを使って作られているものが大多数で、Reactを採用したプロダクトが存在していませんでした(AngularやVueのプロダクトはあります)。
また、HTML&CSSはデザイナーが担当することが多く、フロントエンド側でやることといえば動的な値の表示や条件分岐を組むことくらいでした。
そんなほとんどバックエンドしか書いていなかった人間が、社内で新しくReactを採用するプロダクトが出てきた時やフロントエンドを触ってみたいという人が出てきた時に参考になればいいなという願いを込めつつ、1年間で学んだことや気づきを振り返ります。
基礎的な話
HTML&CSSの知識は大切
JavaScriptを使わずに実現できることを知っておく
detailsタグ、summaryタグによるアコーディオンUI、dialogタグによるモーダル、Anchor Positioning等々、JavaScriptを使わなくても実現できることはたくさんあります。
アクセシビリティも担保されるのでHTMLタグでできることはHTMLタグを使って実装したほうが良いです。
HTMLとCSSでできることは日々増えているので、それらの情報を定期的にキャッチアップしておいたほうがいいです。
セマンティックHTML
上述したような「HTML&CSSだけでこんなことできる」も大切ですが、「セマンティックなHTML」を書くことはそれ以上に大切だと思います。アクセシビリティの向上もそうですが、コンポーネントの意図が明確になるので用途を間違えてそのコンポーネントを使ってしまうことが減ると思います。
コンポーネント設計について
デザイナーとの認識合わせ
コンポーネント設計はデザイナーと認識合わせをする時間を設けたほうがいいと思います。
弊プロダクトでは、全体のデザインを見てコンポーネントに分割していくという時間をとりました。その時にAtomic Designの考え方を共通認識としてもちながらコンポーネントを切り出していきました。
独自解釈やルールを含んでいるのでAtomic Designに忠実に則っているわけではないですが、再利用性を持ちつつ意味のある単位でコンポーネントを整理できていると思います。
余白
基本的にコンポーネントにmarginは持たせないほうがいいです。
コンポーネントを呼び出す親側で制御してあげるとコンポーネントの再利用性が増します。上述したデザイナーさんとの認識合わせでこのコンポーネントの下には絶対にmarginが来るというのが確定しているのであれば話は変わるかもしれませんが、それでもやはり基本的にはコンポーネント自体には余白を持たせないほうがいいと思います。
そういったふうに設計していると、余白どうやって調整しようかという問題にぶち当たると思うのですが、弊プロダクトでは最近spacerコンポーネントを使っています。
責務
コンポーネントの責務を明確にすることは、保守性と再利用性を高める上で重要です。各コンポーネントの独立性を高めるために以下のような点を意識してコンポーネントを設計しています。
上述した余白の話と被りますが、スタイリングの観点ではコンポーネント自体のスタイルとレイアウトに関する責務を分離することを心がけています。例えば、Cardコンポーネントであれば、カードのデザイン(背景色、ボーダー、シャドウなど)はコンポーネント自体が持ちますが、グリッドレイアウトでの配置や他要素との間隔といったレイアウトの制御は親コンポーネントの責務としています。
ロジックの観点では「見た目」と「振る舞い」を適切に分離することを意識しています。例えば、フォームの入力フィールドであれば、入力のバリデーションやAPIとの通信といったロジックは上位コンポーネントやカスタムフックに切り出し、入力フィールド自体は純粋にUIの表示に専念させています。これにより、同じ見た目のコンポーネントを異なるロジックで再利用しやすくなります。
状態管理
使わないので済むのであれば、極力グローバルステートは使わないほうがいいと感じています。
もちろんユーザー情報など、本当にアプリケーション全体で共有しておくべき情報などは別ですが、グローバルステートを使う前に、本当にグローバルステートにする必要があるかを一度検討したほうがいいです。使う場合でも、そのステートをあちこちで更新するというのは避けたほうがいいだろうなと思っています。
バケツリレーが大変みたいな話もありますがchildrenを適切に使っていると、そこまで大変なバケツリレーにはならないんじゃないかなという所感です。
ローカルステートに関しても、むやみやたらに増やさずそのステート管理は本当に必要かというのを一度検討したほうがいいです。
ツール・ライブラリ
もちろん他にも使ってますが、以下の2つだけ紹介します。
StoryBook
新規開発の場合は全ページを見てコンポーネントに切り出すという作業を行った後に、各ページごとに作るのではなく、Atoms、Molecules、一部Organismsレベルのコンポーネント開発を行い、部品を一通り揃えた後にPagesの組み立てを行う流れにしたくなると思います。
その部品単位での開発の時にStoryBookが役に立ちました。新規参入者が来た時にUIカタログとして共有できるのも良い点ですね。
ただ一方で、立ち上げフェーズを過ぎて機能追加の際にはわざわざStoryBookを立ち上げて開発するよりも使用箇所で呼び出しながら開発するほうが速いのでStoryファイルが書かれなくなりがちだったりします。
FigmaのDev Mode(有料)
100%そのまま採用できるわけではないですが、ある程度の精度でCSSを出してくれるし、レイアウトも一目でわかるのでとても重宝しています。
ただ、画像のような状態にするためにはデザイナーがHTML&CSSの知識を持った上で、うまくFigmaを使いこなさないとダメなようなので弊社のデザイナーに大感謝です。
その他・感想・課題感
開発効率
「コンポーネントの認識合わせ」に多少時間はかかりますが、それを済ませてしまえばその後の開発効率は格段に上がると思います。新規参入者が来たときも、使うコンポーネントだけ伝えれば実装に集中してもらえます。
弊社の他のプロダクトは全体的にCSS設計にBEMを採用しています。弊社のエンジニアにHTML&CSSも書こうよというと「CSSはちょっと・・・」という反応をされることが多いです。その反応の原因はBEMの命名規則を覚えることに壁を感じているのではないかなと勝手に想像しています。
そのため、BEMなどのCSS設計手法が解決しようとしているスコープの問題を自然に解決してくれるのは大きいなと思います。
私はもともと少しだけRails×ERBを書いていたのですが、Reactに近い開発体験を得ようとするとView ComponentsとTailwindを併用すると実現できるのでしょうか(それはそれでつらみがあるのかどうかは使ったことないのでわからないです)。
キャッチアップ
HTMLもCSSもJavaScriptもあまり書いたことがないバックエンドエンジニアがReactを書こうとすると、おそらくまず「コンポーネントって何」「stateって何、set関数って何」「宣言型UIってなに」ってなにみたいなところから躓くと思います。
どうやったらこの辺をスムーズに理解してもらえて、独りで書けるレベルまで素早くもっていけるのだろうと、新しくReactに触れるメンバーが入ってきた時には頭を悩ませています。
あると良い知識
フロントエンド開発をするにあたって、DB設計やAPI設計などのバックエンドの知識あったほうがいいだろうなと感じています。
現状バックエンドのAPIも自分で作っているのですが、もしチームが拡大してフロントエンドとバックエンドを分業するみたいなことになることになるかもしれません。
その場合バックエンドの知識があると「ユーザー体験のためにこういうAPI」が欲しいとなった時に、パフォーマンスのことを考慮して提案したり、既存のAPIを組み合わせて目的を達成する方法を考えたりでき、建設的な議論ができそうだなと思っています。
まとめ
1年間の実践を通じて、Reactによるフロントエンド開発は初期の学習コストはあるものの、コンポーネントベースの開発による保守性や再利用性の向上、開発効率の改善など、多くのメリットを実感できました。今後も新しい技術や手法をキャッチアップしながら、より良い開発を目指していきたいと思います。
Discussion