> For the complete documentation index, see [llms.txt](https://docs.wantedly.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.wantedly.dev/fields/apps/frontend-architecture.md).

# Web アプリのアーキテクチャ

本章では、生産性の高い状態で継続的に開発していくために、Web アプリのアーキテクチャについて議論した内容について紹介します。

## 技術スタックの現状

これまでのリニューアル[^1]、リノベ[^2]、リファインメント[^3]によりプロダクトのUIがアップデートされ、それに伴いフロントエンドの技術スタックもアップデートされてきました。 現在技術スタックは大きく4世代存在し、v1〜v4 と呼ばれています。

| version | 構成                                                                           |
| ------- | ---------------------------------------------------------------------------- |
| v1      | Haml / SCSS / AngularJS & jQuery & Backbone.js                               |
| v2      | TypeScript + React + Redux + redux-thunk / styled-components / webpack       |
| v3      | TypeScript + React + Redux + redux-thunk / styled-components / webpack / SSR |
| v4      | TypeScript + React(Next.js) + GraphQL / styled-components                    |

最新のバージョンは v4 です。現在でも v4 以前の古い世代の技術スタックで書かれたコードが存在します。

## 開発における基本方針

新規開発やページのリニューアルのタイミングでは可能な限り v4 で開発することを推奨します。 v4 アーキテクチャの各アプリケーション上で開発を行い、 GraphQL サーバーを経由して各マイクロサービスと通信を行うようにします。

### v4 アーキテクチャのアプリケーションについて

v4 のアーキテクチャのアプリケーションは以下の２つが存在します。

| アプリケーション                | 対象          |
| ----------------------- | ----------- |
| wantedly-frontend       | ユーザーサイト     |
| wantedly-admin-frontend | 企業向けユーザーサイト |

対象に記載がある通りそれぞれのアプリケーションがユーザーサイトと企業向けユーザーサイトに分かれています。 対象となる機能がユーザー向けであるか、企業向けであるかをもとに開発するべきアプリケーションを確認してください。

### GraphQLサーバーについて

WantedlyにはGraphQLサーバーが以下の2種類存在します

* wantedly-graphql-gateway
* visit-api-node

サーバーが2つ存在する経緯等については [Wantedly Visit で BFF GraphQL サーバーを辞めた理由](/fields/the-system/history-of-graphql.md) を参照ください。 新規ドメインの query/mutation は基本的に wantedly-graphql-gateway に用意されます。

## 実装における共通方針

### 技術方針の決定プロセス

新しい技術やライブラリを導入する際は以下の手順で進めます：

1. Frontend Chapter で議論を行う
2. 撤退可能な状態・最小規模で導入する
3. Architecture Decision Record (ADR) に記録する
4. 振り返りを行う
5. 振り返りをもとに判断を行い、必要であれば広く導入する

小さく試す限りにおいては上記の手順はSkipしても問題ありませんが、判断に困る場合は上記に従うことを推奨します。

### SSR

SSR が可能なアーキテクチャにおいては SSR は必ず行う前提で実装を行います。 一方で SSR の際、つまりサーバーサイドで多数の GraphQL の呼び出し等をすると TTFB (Time to First Byte) が遅くなる原因になります。

![TTFB image](/files/KsxpnDsMf4IIcPuKM3Cv)

そのため、何をサーバーサイドで同期的に取得し、何をクライアントサイドで非同期的に取得するかを個々のページで考慮する必要があります。 例えばファーストビューで表示されるコンテンツ SEO に必要な meta 情報はサーバーサイドで同期的に取得する必要があります。 一方でパーソナライズされたコンテンツ、例えばユーザーへおすすめのコンテンツなどはクライアントサイドで非同期的に取得を行っても問題ありません。

![TTFB image](/files/ucNhfP0iPrUBcb9Z6LxP)

画面の性質を考慮した上で適切な設計を行うようにしてください。

### 状態管理

Web アプリの状態管理は以下の3種類に分けることができます。

| No. | 種別名          | 概要                                |
| --- | ------------ | --------------------------------- |
| 1   | サーバーデータキャッシュ | サーバーから取得したデータをクライアント側でキャッシュしているもの |
| 2   | グローバルな状態     | 複数画面/コンポーネントで保持するUIの状態            |
| 3   | ローカルな状態      | 単一のコンポーネントが保持するUIの状態              |

これらの状態管理をそれぞれの技術スタックで以下のように状態管理を行ないます。

**1. サーバーデータキャッシュ**

| 技術スタック | 何を使っているか             | 補足                        |
| ------ | -------------------- | ------------------------- |
| v1     | -                    | フロントエンドでのデータキャッシュは行なっていない |
| v2, v3 | Redux Store          | 一部 React Query を利用している    |
| v4     | Apollo InMemoryCache | -                         |

**2. グローバルな状態**

| 技術スタック | 何を使っているか    | 補足                                                        |
| ------ | ----------- | --------------------------------------------------------- |
| v1     | -           | 単一の状態管理を持たない                                              |
| v2, v3 | Redux Store | -                                                         |
| v4     | -           | 必要に応じた Context API を利用した状態管理はあるが Redux のように中央集権の状態管理は持たない |

**3. ローカルな状態**

| 技術スタック | 何を使っているか               | 補足                                       |
| ------ | ---------------------- | ---------------------------------------- |
| v1     | -                      | 単一の状態管理を持たない                             |
| v2, v3 | Redux Store / useState | Redux Store が存在する場合は Redux Store を利用している |
| v4     | useState               | -                                        |

前述のとおり v4 では Redux のような中央集権的な状態管理の仕組みは存在しません。 これはグローバルな状態管理のために Redux, Jotai, Zustand などのライブラリを使用しない、という判断ではありません。 v4 において複雑な状態管理が必要になった際には新規にライブラリを導入するという判断は可能です。 技術方針の決定プロセスの手順に従い導入を進めるようにしてください。

## v4 へのマイグレーション・移行

wantedly/wantedly の v1 スタックのページについてはリノベ・リニューアルのタイミングで積極的に v4 への載せ替えを推奨とします。 移行については以下のいずれかの方針で進めることを推奨します。

* v1 から v4 へ完全移行（GraphQL API への移行も含む）
* v1 から v4 へフロントエンドを移行（GraphQL APIは対応せず、既存のエンドポイントを利用する）
* v1 から v2, v3 へ、その後 v4 へ段階的に移行する

どのような方針で進めるべきか迷った場合はまずは Frontend Chapter で相談をしてみてください。

#### 話を聞きに行きたい

* Slack: [#frontend\_chapter](https://wantedly.slack.com/archives/CA46K091P)

#### もっと知りたい

* [Wantedly Visit のウェブフロントエンドの構成の歴史 (internal)](https://github.com/wantedly/wantedly/blob/master/doc/frontend_history.md)
* [Wantedly のこれからの Frontend Architecture を考える (internal)](https://github.com/wantedly/dev/issues/444)
* [Frontend Architecture を考える 2021春 (internal)](https://docs.google.com/document/d/1U-Rwad-R76RgQ0OrDvhT0BBc_pcNOKZiH3h0Eb25Pe8)
* [Web Frontend Directory structure 2021 秋 (internal)](https://docs.google.com/document/d/1BqczG15wWQxtXszo2T6FU7JwbnIv3baG9PEMdRvEGO8)

[^1]: フロントエンド/バックエンド含めてアーキテクチャ/機能/UIを刷新する。（e.g. 2019-2020年頃の募集作成画面、スカウト画面のリニューアルプロジェクト）

[^2]: バックエンドは変更せず、UIのみを大幅に変更する。（e.g. 2020-2021年頃の採用管理画面 UI 刷新プロジェクト）

[^3]: UI は維持したまま、フロントエンド/バックエンドの刷新を行う。（e.g. 募集一覧画面、募集詳細画面の v 1→ v4 移行プロジェクト）
