こんにちは。WEAR部フロントエンドブロックの藤井です。WEARでは現在、Webサイトのリプレイスを進めています。本記事では、リプレイスに至った背景や課題と、課題解決のために行ったリプレイスのアーキテクチャ選定についてご紹介します。
WEARはサービスローンチしてから約10年が経ちます。これまでローンチ当時の技術スタックのまま開発を続け、サービスを成長させてきました。今後もより継続的にスピード感を持ってユーザーへ価値を届けていくにあたってさまざまな課題があったため、新たな技術スタックでリプレイスを開始することにしました。
リプレイス前の環境はオンプレミスの環境にロードバランサー、Windowsサーバー(IIS)があり、そこでVBScriptが動いています。VBScriptでテンプレートHTMLにデータを流し込み、ブラウザに表示する仕組みで動いています。フロントエンド部分はjQueryを使用し、インタラクションの実装、Ajaxで取得したデータを元に後読みでコンテンツの描画などを行っていました。
上記の環境で長らく開発を進めていましたが、サービスの成長や機能の増加に伴って以下のように生産性、保守性に関する課題がでてきました。
今後、WEARのサービス改善をスピード感を持って実行していくためにはこれらの課題を改善する必要がありました。このような背景からリプレイスを始めることにしました。
リプレイスを進めるにあたって課題を解決するだけではなく、リプレイスで実現すべきミッションについて改めて整理しました。そして、そのミッションを元にアーキテクチャを選定しました。
リプレイスのミッションを考えるときに軸となったのは、WEARのプロダクトとしてのミッションでした。WEARはミッションとして、”ファッションデータを集めて、人々のファッションの悩みを解決する”を掲げています。より多くの人にコーディネート投稿をしていだき、より多くの人にファッションデータを届けることで、このミッションを実行しようとしています。
このミッションの元、WEARのWebサイトで何をすべきかをチームで話し合い、以下の方針を決めました。
MUSTの要件としてはまず、課題であった開発生産性を向上させることを挙げました。次に、できるだけ早くユーザーに快適なリプレイス環境を利用してもらうために必要な機能を取捨選択することを決めました。機能を取捨選択する際にはユーザーの利用状況を確認し、数値を元に判断しています。
WANTの要件にはSEO改善を目的として、パフォーマンス、UXの向上を挙げました。WEARのWebサイトはSEO流入で閲覧してくださるユーザーがとても多いです。そのためWEARのMissionのうち、”より多くの人にファッションデータを届ける”ということを重視してSEOへの注力をミッションに決めました。
リプレイスのミッションに沿って、開発生産性の向上と、SEO改善目的でパフォーマンスを重視した技術選定をしました。
フレームワークは当初、Preact+Fastifyで検証を進めていたのですが、最近になってNext.jsを選択することにしました。それぞれの選定理由や選定までの経緯を説明します。
まず初めに選定したアーキテクチャは以下のような構成で、Preact+Fastifyを使用していました。
SEO改善目的でパフォーマンスを重視した選定になっています。FastifyはNode.jsフレームワークとしてよく使われるExpressよりも高いパフォーマンスであることから採用しました。Preactはファイルサイズが大きいReactDOMを使用せず軽量化されているため採用しました。
処理の流れとしてはまず、Build時のSSG(Static Site Generator)やサーバー上でのSSR(Server Side Rendering)で生成したHTMLをブラウザに返します。基本的にSSGやSSRではSEOに重要な情報について扱います。そして、SEOに必要のない部分やログインユーザーの情報に関わる部分はCSR(Client Side Rendering)用のJavaScriptを生成し、ブラウザ側でレンダリングするようにしています。まずこちらのアーキテクチャで簡単なページから検証とリプレイスを進めることにしました。
パフォーマンス目的でこのようにCSR部分を分離した構成にしていたのですが、リプレイスを進めたところ以下のような考慮点がでてきました。
上記を踏まえ、WEARのWebサイトにおいてこのアーキテクチャで進めるべきか考えたところ、以下の課題がありました。
先述したような課題がわかったため、アーキテクチャを見直して以下のようにNext.jsを使用することにしました。
Next.jsを選定した理由は以下のメリットがあったためです。
もともと、Preactのファイルサイズが軽量であることの恩恵としてCore Web Vitalsの指標にあるFirst Input Delayの短縮を見込んでいました。しかし、上記に挙げたようなメリットや開発効率を優先させてNext.jsへの移行を決めました。
リプレイスするにあたってエッジサーバーとしてFastlyを導入しました。一番の目的はパスベースルーティングをさせるためです。
WEARは日々新しい機能追加や機能改善をしているサービスなので、1回で全機能を切り替えるのは難しいという背景ありました。そのため、以下のようにFastlyを用いて、パスベースでリプレイス前の環境とリプレイス環境に割り振ってルーティングし、段階的にリプレイスを進めています。
Fastlyを選定した理由や詳しい活用方法については以下の記事で紹介されているので、併せてご覧ください。
Fastlyのもう1つの活用方法として、CDNキャッシュを利用して素早くページを表示することによるユーザー体験の向上とSEO改善を検討しています。安全にキャッシュを利用できるようにログインしているユーザー情報に関わらない部分のみをビルド時やサーバー側で生成します。そして、ユーザー依存情報はuseEffectなどのフックを利用してCSRで描画されるようなコンポーネント設計にしています。
WEARではWebのリプレイスと並行してバックエンドチームにWebリプレイスで必要なAPIをリプレイスを進めてもらっています。リプレイス前の環境ではAPIの開発を待つか、モックAPIを作成してもらってAPIデータ取得部分の実装をしていました。そのため、フロントエンドとバックエンドを同時並行で開発を進めることがなかなか難しい環境でした。しかし、Mock Service Workerを使うことによって、Swagger定義があればAPIの開発を待たずにAPIデータ取得部分の実装を進められるようになりました。
スタイリングについては以下のような理由でTailwind CSSを選定しました。
UIのカタログ化のために導入しました。リプレイス前は共通UIがあることに気づかず個別に実装してしまうということなどもあったのですが、カタログ化することでこの問題が解消されました。また、初めは個別に実装していた箇所についてもカタログ化していることで共通性に気づいて後から共通コンポーネントに移すということもあり、コンポーネント整理に役立っています。
Chromatic、Mock Service Worker、Storybookを連携させてビジュアルリグレッションテストを行なっています。スタイルの差分を検知してくれるようになったので、今まで目視で細かくチェックしていた時間を削減でき、開発やレビュー時間の短縮につながりました。
Chromatic、Mock Service Worker、Storybookを使った取り組みについてはFAANS部の田中が以下の記事で紹介しているので、併せてご覧ください。
WEARではプロダクトのミッションやサービス特性を元にアーキテクチャ選定をしました。アーキテクチャ選定の際にはいくつかの観点でメリット・デメリットを挙げて検討しましたが、特に重きをおいたのは以下の3点です。どれか1つに偏ることなく、サービスとして欠かせない点や許容できる範囲を見極めることが大切だと思います。
ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。