モノタロウのフロントエンド刷新の取り組み①~大規模ECサイトのフロントエンドをドメイン単位で再設計した話

こんにちは。モノタロウでECサイトの開発・運用を担当している池です。

モノタロウではECサイトのフロントエンド刷新に取り組んでおり、その内容をブログで共有したいと思います。よろしければ、関連記事もあわせてチェックしてみてください。

私が所属するフロントエンドモダナイゼーションチームは、ECサイトのフロントエンドをNext.js/Reactベースの新システムに刷新するプロジェクトに取り組んでいます。この記事では、ドメイン単位で再設計した新システムの方針と構成を紹介します。

背景と課題

モノタロウは事業者向けの間接資材ECサイトで1,000万を超えるユーザーに利用されていますが、フロントエンドのシステムにいくつかの課題がありました。

従来のフロントエンドはレガシーな技術や一部独自フレームワークへの依存があり、OSSエコシステムやコミュニティの知見を活かしにくい状態でした。そのため開発生産性がなかなか上がらず、高度なUXの実現や継続的な改善にも制約がありました。また、設計の異なる複数のシステムで構成されていたため、コードや知見の共有も難しく、価値提供のリードタイムが長くなっていました。さらに、各ドメインの開発チームが複数システムすべてを担当する体制で、認知負荷の高さも生産性を下げる要因でした。

方針

「ドメインチームの生産性を最大化すること」をゴールに、3つの方針を立てました。

システム設計のモダン化/標準化: レガシー技術や独自フレームワークから脱却し、React・Next.jsなど広く普及した技術スタックに移行する

コード/モジュールの共通化: 技術スタックのベースを統一し、共通コードをパッケージ化して再利用できる仕組みを整える

システムと開発組織のアラインメント: チームの担当範囲とシステムの境界を一致させ、各チームが自律的に開発・改善を進められる体制にする

具体的な取り組み

システム設計のモダン化/標準化

以下の技術スタックを共通ベースとして採用しました。十分な実績とコミュニティを選定基準に、各ドメインチームがビジネス要件に応じてライブラリを追加できる柔軟性も確保しています。

カテゴリ 技術
フレームワーク Next.js
UIライブラリ React
言語 TypeScript
スタイリング Sass/SCSS(CSS Modules)
API(BFF) Nest.js(GraphQL)
コンポーネント管理 Storybook
テスト Vitest
モノレポ管理 Turborepo

詳細は今後の記事で紹介しますが、この記事ではStorybookを取り上げます。UIコンポーネントの管理にとどまらず、デザイナーとエンジニアの協働スタイルや開発プロセス全体を変えるきっかけになったためです。

Storybookの活用

Storybookはコンポーネントを独立した環境で開発・確認できるツールで、APIやバックエンドの実装状況に依存せずUI単体で動作を検証できます。このUI層とデータ取得・ビジネスロジック層を切り離した開発スタイルが、開発フローやデザイナーとの連携にも大きな変化をもたらしました。

従来の開発フローは、デザイナーが画面設計書を作成 → エンジニアが実装 → リリース後に画面仕様書を作成、というものでした。Storybookの導入でこのフローが2つの点で改善されました。まず、画面設計書はあくまで中間成果物なので、StorybookでUIを直接確認できれば作成コストを削減できます。また、APIに依存せずコンポーネント単体のインタラクションを確認できるため、開発の早い段階でUXを検証でき、手戻りを大幅に削減できます。加えて、リリース後の画面仕様書はメンテナンスコストが高いという課題もありましたが、StorybookをUIの仕様書として活用することで、常に最新のUI状態を参照でき、ドキュメントの陳腐化を防げます。

一方、StorybookはUIコンポーネント中心の構造上、自由な形式での説明や図の挿入といった表現力では通常のドキュメントツールに劣ります。仕様の背景や設計意図など、コンポーネントの枠を超えた情報を残すには別途工夫が必要です。

共通で利用するUIをStorybookでカタログ化した取り組みについては、本連載の別記事で詳しく紹介する予定です。ぜひそちらもご覧ください。

コード/モジュールの共通化

ドメインの独立性を保ちつつ共通基盤やツールチェーンの恩恵も受けるため、モノレポを採用しました。

私たちのチームでは packages/ 配下の共通パッケージ、再利用可能なCI/CDワークフロー、監視ツール連携の仕組みなどを整備し、ドメインチームがサービス開発に集中できる環境を整えています。apps/ 配下のドメインアプリはGitHubのコードオーナーで管理し、共通パッケージはGitHub Packagesでバージョン管理することで、共通利用しながらも予期しない変更の影響を防いでいます。Turborepoによる依存関係の解決やビルドキャッシュの最適化も活用し、モノレポの運用負荷を抑えています。

frontend-monorepo/
├── apps/                    # ドメインアプリケーション
│   ├── product/             # 商品関連ページ
│   ├── order/               # 注文関連ページ
│   ├── bff/                 # 共通BFF
│   └── ...
│
├── packages/                # 共通パッケージ
│   ├── ui/                  # UIコンポーネント
│   ├── shared-features/     # ナビゲーション、カートインポップアップなど共通機能
│   ├── shared-lib/          # 共通ライブラリ
│   ├── recommend/           # 販促エリア
│   ├── eslint-config/       # ESLint設定
│   ├── typescript-config/   # TypeScript設定
│   └── ...
│
└── turbo.json               # Turborepo設定

BFF(GraphQL)によるデータ取得の共通化

フロントエンドが必要とするデータは、マイクロサービスから直接取得するのではなく、GraphQLサーバー(BFF)経由で取得する方式にしました。直接取得する方式と比べてネットワークリクエストが増える分レイテンシーは上がりますが、次の2つのメリットからBFF方式を採用しました。まず、社内で進化し続けるマイクロサービスの変更をBFFで吸収でき、フロントエンドへの影響を最小限に抑えられます。また、各ドメインアプリからGraphQLクエリで宣言的にデータを取得でき、他ドメインのデータも柔軟に参照できます。

BFFのデプロイ単位は1つのアプリですが、NestJSのモジュールシステムを活用してドメインごとにオーナーシップを分けられる設計にしています。

modules/features/ 配下にドメインごとのモジュールを配置し、各モジュールはResolver・Service・DataLoader・Repositoryの4層構造で統一しています。modules/shared/ にはDB接続・認証・ロギングなどのインフラ基盤を集約し、各Featureモジュールから共通利用できるようにしています。これら各ドメインのFeatureモジュールを GraphqlFeatureModule に集約し、1つのGraphQLアプリとして統合することで、利用側はドメインを跨いだデータ取得をクエリを用いて宣言的に行うことが可能になります。

// modules/features/index.ts
@Module({
  imports: [ItemsModule, ReviewModule, PricesModule, AvailabilityModule, /* ... */],
})
export class GraphqlFeatureModule {}

BFFの導入背景や取り組みの詳細は、本連載の別記事で紹介予定です。ぜひそちらもご覧ください。

システムと開発組織のアラインメント

ユーザーから見るとサイトの入り口は1つですが、裏側はドメインごとに異なるアプリケーションが動いています。リバースプロキシがリクエストのURLに応じて担当ドメインのアプリへルーティングし、各ドメインアプリは共通パッケージを組み込みつつ独立したサーバーとして動作しています。

ドメインの境界は関連するページ群を単位に引いていますが、レコメンドエリアのようにドメインをまたいで使われる機能は packages/ でライブラリとして管理し、各ドメインアプリのビルド時に組み込んでいます。クライアントサイドで動的に読み込めば各パッケージを独立デプロイできるメリットもありますが、現時点では変更頻度や外部設定によるデザイン制御の要件を考慮し、ビルド時統合のシンプルな構成を選びました。

各アプリケーションは独自のCI/CDパイプラインを持ち、テスト・ビルド・デプロイまで独立した環境で運用できます。他チームの影響を受けずにリリースタイミングをチーム内でコントロールできます。

おわりに

今回は大規模ECサイトのフロントエンドをドメイン単位で再設計した取り組みの全体像を紹介しました。設計や運用の詳しい話は、今後の記事で掘り下げていきます。

今回紹介した構成は最終形ではなく、フロントエンド技術の進化やビジネス要件の変化にあわせて継続的に改善していく予定です。

私たちの取り組みに興味を持っていただけたら、カジュアル面談など気軽にお声がけください!

カジュアル面談で話を聞いてみる