hiring!はじめに初めまして。2024年2月にDIGGLEにエンジニアとして入社したfujitaです。JS、JQueryでの簡単なDOM操作やAjax通信の実装を行った程度の経験しかありませんでした。DIGGLEでは基本的にエンジニアはバックエンド・フロントエンドの両方の開発に携わるため、フロントエンドの開発に取り組むにあたって、いくつかの困難に直面しました。具体的には、DIGGLEではReactを用いたシングルページアプリケーション(以下、SPA)として構築されており、これまで経験したことがないほどにフロントエンドのコードベースの規模が大きく複雑なため、以下のような難しさがありました。機能を追加・改修するために、どのファイルのどの部分を修正すべきかがわからないコードを修正した際に、その影響範囲を把握することが難しいしかし、フロントエンドにおけるアプリケーションアーキテクチャ(以下、アーキテクチャ)、簡単にいえば各ディレクトリ、ファイル、コンポーネントの役割・責務を理解していくにしたがって、これらの困難は徐々に解消され、開発スピードも向上してきました。本記事では、私がReactを用いた大規模なSPA開発に初めて取り組む中で得た知見や、DIGGLEのフロントエンドアーキテクチャがどのように設計されているかについて共有したいと思います。Reactを用いたSPAのアーキテクチャSPAのアーキテクチャ基本的なSPAのアーキテクチャとしては、バックエンドでも用いられるMVCや、それが発展してできたMVVMがあり、これらは総称してMVW(Model-View-Whatever)と呼ばれます。これらはいずれもアプリケーションのデータやロジックをもつModelと、UIでありModelの視覚的表現であるViewを要素としてもちます。ViewModel)によってViewとModelを適切に分離しつつ連携できるようにします。この分離によって、コードの可読性、保守性、テスト容易性などが向上します。ReactReactはUI構築のためのJavaScriptライブラリです。Vを担当し、アーキテクチャとは直接関係しません。宣言的にコンポーネントを作成することができ、状態の変化に応じたUIの更新はReactが裏側でやってくれますが、どのようにアプリケーションのデータを取得・管理し、Reactコンポーネントへ渡すかなどは別に考えなければなりません。フレームワークの使用が推奨されています)さらに、先ほどReactはMVWのViewに相当すると述べましたが、Reactコンポーネントは自身の状態を管理・更新したり、副作用を扱ったりでき、View以上のものといえます。そのため、一般にReactではMVWとは異なるアーキテクチャが採用されます。代表的なアーキテクチャとしてFluxなどがありますが、開発チームの事情に応じて様々な選択肢があるようです。次項で、DIGGLEのアーキテクチャの一部をご紹介します。Container/Presentationalパターンが、関心の異なるロジックを分離するためにHOCパターンが用いられています。状態管理については記事がありますので、ぜひご覧ください。Componentに分割することで、UIと状態・ロジックを分離します。具体的には以下のようになります。Componentは状態管理APIからグローバルな状態(ログインユーザーの状態など)を取得します。ComponentはバックエンドAPIをコールし、リソースのデータを取得します。レスポンスからViewModelを作成し、それを状態として保持します。ViewModelはMVVMにおけるものとは若干異なり、APIで取得したデータとそれに関連するメソッドを含んだオブジェクトです。Componentからpropsとして受け取り、UIを構築します。以下の記事を参考にさせていただきました。zenn.devコードの例を見てみましょう。以下は、レポートの作成年月やタイトルなどを表示するコードです。レポートに関するデータとメソッドをもちます。ComponentAPIをコールしてレポートのデータを取得後、ViewModelを作成し、状態として保持します。Componentレポートの作成年月、タイトルを表示します。);};メリット前述したアーキテクチャを取り入れることのメリットであるコードの可読性、保守性、テスト容易性などの向上が得られます。主要なデータやロジックが、他のコンポーネントと分離された形でViewModelに含まれるため、ViewModelに対するテストを重点的に書くことで、効率的にテストの恩恵を受けられます。Component)に分離します。高階コンポーネントとは、あるコンポーネントを受け取って新規のコンポーネントを返すような関数です。以下のModalizeはモーダル表示に関連するデータや状態をもつコンポーネントです。モーダルで表示したい場合は、以下のようにします。Modalize(MyComponent);メリットモーダル表示に関連する状態やロジックが分離されているため、これを様々なコンポーネントをモーダル表示するために再利用することができます。複数の高階コンポーネントを自由に組み合わせることもできます。WithAsync(Modalize(MyComponent));ただし、高階コンポーネントの数が増えるとコードが読みにくくなります。HOCn(...(HOC2(HOC1(MyComponent)))...);デコレータを利用すると以下のように書けます。@HOCn...@HOC2@HOC1MyComponentデコレータの詳細は以下をご覧ください。github.comwww.typescriptlang.org今後の展望ここまで紹介したコードを分離するためのパターンは、コンポーネントを利用したものでした。そのため、不必要な再レンダリングを引き起こす可能性があったり、テストが難しかったりする場合があります。これらの問題を解決し、より簡単かつシンプルにコードの分離を行うために、今後、Hooksの活用を積極的に進めていきたいと考えています。根本的な目標は、ReactのHooksを活用した宣言的アプローチへの進化に追随することで、Reactの利点を最大限に引き出し、プロダクトの価値を高めることです。共にプロダクトを開発してくれるエンジニアを大募集中です。興味があれば、ぜひ下記採用サイトからエントリーください。採用した話こんにちは。Libraryのrerenderを薄くラップすることで使い勝手を向上させ...こんにちは。エンジニアの伊藤です。1引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。