Skip to main content

マイクロフロントエンドのビルドパイプラインで革命を起こす

8月

25, 2020

by jynj2912


テック

Robloxのウェブアプリケーションは、一枚岩として構築されました。下の図式のように、一つのプロジェクトの開発をしているすべてのエンジニアが一緒にリリースすることが必要です。プロジェクトは、Asp .Net Web Formを含む .Net MVCの枠組みを使って構築されました。そのため、どのような変更でも適用するにはJS/CSS/Image変更であってもMSBuildが必要です。

ビルドとデプロイ

消費者の側では、ウェブアセットの読み込みには2つのシナリオがあります。ブラウザが最初にリソースをリクエストする場合と最初のリクエスト以降にCDNから引き出す場合です。 以下のフローチャートは、CDNへのアセットのアップロードがどのように最初の読み込み作業に含まれているかを示しています。

それから、最初の読み込みシナリオの後、そのようにブラウザはCDNからリソースを引き出し始めます。

10年以上の継続した開発と年季の入ったコードベースのため、当社の開発とリリースパイプラインはCDNから期待できるような効率に欠けていました。 これは、いくつかの理由で起きました。

  • ウェブアセット変更(Javascript、CSS、HTML、画像、その他)だけだったとしても、ウェブサイト全体をビルドしてデプロイする必要があります。
  • もし、変更によって何らかの問題が発生した場合、違うチームによるすべてのコミット済みの変更は、問題が解決するまでリリースを待たなければなりません。

加えて、ウェブアセットはバンドルにされて、クラスメソッドによってCDNにアップロードされ、ES6+(ECMAScript 6+) やTypescriptのような現代的なフロントエンドテクノロジーを長期的な開発には適応させにくくしています。 そのため、現在のビルドとデプロイパイプラインは、全員にとって障害を作り出します。

2017年から、Robloxはウェブアセットのビルドとデプロイ導入の過程を分けるために様々なアプローチをテストしました。

  1. 最初に成功したアプローチは、より小さいAPIサイト作成で学んだことをアプリサイト作成に応用することでした。 アプリサイトは、コンポーネントごとにウェブアセットを含んでいて、自分のプロジェクトとしてデプロイします。 アプリサイトは、個々のウェブサイトではなく、むしろアセットをバンドルする終了点を与えて、リダイレクトされたCDN URLを返します。
  2. 第二段階は、新しい静的コンテンツサービスと共にアセンブリクラスメソッドの代替としてのWebpackバンドルシステムの導入です。 これによってバンドルをCDNにアップロードすることができ、それによってウェブサーバーデプロイを削除して、それぞれのコンポーネントでCDN URLだけをアップデートします。

第一段階 – ウェブアプリ(サイト)

フィーチャーコンポーネントのいくつかのために、すでにモダンJSフレームワークを開発したため、Robloxのメインのウェブサイトからクライアント側のレンダリングプロジェクトを分離させることから開始するのは自然なことです。 主要プロジェクトをスケルトンとして扱うため、主要プロジェクトが知らなければならないことは、どのウェブアプリサイトをリクエストするかだけです。 そして、それぞれのプロジェクトは似たようなフィーチャーコンポーネントとそれ自身のアセットをホスティングします。

プロジェクト内のそれぞれのコンポーネントには、Javascript、CSS、HTMLをバンドルする終了点を提供する独自のコントローラーがあり、終了点の応答はCDN URLにリダイレクトします。 例えば、終了点としてのhttps://chatsite.roblox.com/chat/{version}/get-javascript-bundlehttps://js.rbxcdn.com/{hashNumber}.jsを返します。 リダイレクト応答は、301 Httpステータスで応答は最初のリクエスト後にキャッシュされます。

ブラウザに変更を通知するために、キャッシュ対策の目的で、アプリサイトURLにバージョン番号を追加します。 バージョン番号はGUIDで、管理者サイトから追加したりアップデートしたりできます。 アプリサイトから行ったそれぞれの変更に対して、開発者はアプリサイトをデプロイしてから、管理者サイトに行って、キャッシュをフラッシュするためにGUIDをアップデートする必要があります。

そのため、バンドルのために同じMSBuildシステムを受け継ぎますが、それぞれのプロジェクトの所有者が変更(以下のような)をリリースする柔軟性を持っています。

ビルドとデプロイ

このアプローチの利点は、エンジニアが新しいコードをデプロイした時、2つの段階しか踏まなくていいことです。 まず、必要な変更がしてあるアプリサイトをリリースします。 そして、ブラウザにアップデートがあったことを告知し、アップデート済みのリソースを取り出すために、それぞれのアプリサイトURLのハッシュ値をアップデートします。 初めて以下のようにアップデートされたURLによってブラウザがリソースをリクエストし、CND URLが準備できる前に関連するURLからリソースをダウンロードします。

最初の読み込みの後、一度CDN URLが準備できると、ブラウザがCDNから直接、リソースを取り出し始めます。 以下ように

現在、このアプローチでは、ウェブサイトへのリリースをすることなしにそれぞれのコンポーネントに対して変換リソースを提供できます。 変換リソースはバンドル化を必要とせず、JSファイルの一部としてLocaleResourceFactoryから変換リソースを取得するのに独自の終了点があります。

プロジェクトは、アセットをバンドルしてCDNにアップロードするのに同じクラスメソッドを受け継ぎます。 このメカニズムは、関連したパスに留めるためには、CSS規則からの画像読み込みが必要です。 CSSバンドルは、静的ファームであり続け、画像は物理的に同じサーバーに留まります。 そのため第一段階では、以前のようにメインのウェブサイトから画像が引き続きアップロードされます。

利点

  • 開発者は開発することができ、ウェブJavascript、HTML、またはCSSなど、自分のウェブアセットのどのFE変更も公開できます。
  • 開発者は、ウェブリリースのかわりに消費者アプリサイトをリリースするだけで翻訳の文字列をアップデートできます。
  • 副作用として、クライアント側のレンダリングページは、クライアント側のレンダリングリファクターでチームをより速く動かすようにするアプリサイトのビルドパイプラインからデプロイできます。

欠点

  • レガシーバンドルシステム再利用によって、画像とモダンJSはアプリサイトからは、まだ簡単に開発したり、デプロイすることができません。
  • ブラウザがアプリサイトにリクエストを送信するときにバンドルが生成されるため、新しいCDN URLがうまく生成されなかったり、破損状態になる可能性があるときに、ブラウザを次のアップデートの前にキャッシュできます。

第二段階 – ウェブアプリ(フォルダ)

第一段階の後、明らかな疑問が浮上しました。アプリサイトからCDN URLをなぜリダイレクトしなければならないのでしょうか? 主要なウェブサイトコードになぜCDN URLを埋め込めないのでしょうか?

第二段階を静的コンテンツサービスを導入するためにビルド期間にS3へウェブアセットをアップロードして、それから第一段階のコンポーネント構造を引継ぎつつCDN URLをDBに返します(そして、Robloxウェブサイトをスケルトンとして保ちます)。 それぞれのコンポーネントリソースバンドルが静的コンポーネント列挙型(Enum)文字列の名前にマッピングされます。 コンポーネントの名前はウェブサイトのスケルトンページに埋め込まれます。

ウェブサイトは、コンポーネントの名前によって最新の有効化済みコンテンツを静的コンテンツサービスにリクエストし、 キャッシュされていない場合はCDNがS3から引き出すCDN URLを返します。 そして、この静的コンテンツサービスの利点があれば、ビルドしている時間内にまとめ終えます。 そして、CDN URLは新しいバージョンと認証を有効化する前に準備ができます。 CDN URLをRobloxウェブサイトプロジェクトに直接、埋め込んだため、CDN URLを取得するためにさらにアプリサイトに行くためにウェブサーバーをデプロイする必要がありません。 これは、開発者がウェブサーバーからデプロイする手間を省きます。

エンジニアが変更を一番最初にデプロイするとき、管理者サイトからそれぞれの静的コンポーネントバンドルのCDN URLをアップデートするのに一段階しか必要ありません。 まだキャッシュされていないため、URLはCDNから直接、取り出されます。

一番最初の後は、CDN URLはブラウザが静的コンテンツサービスからリクエストするときに利用できます。

第二段階の2つ目の部分は、現在のバンドルシステムをWebpackツールで置き換えることです。 SCSSコンパイラを適用したり、アセットをマージしたり最小化したり、イメージをアップロードしたり、ES6をコンパイルしたり、ソースマップするのにWebpackが使用されてきました。 このwebpackツールは、MSBuildからのウェブのフロントエンドプロジェクトをデカップルするので、それぞれのウェブアプリがリソースを維持するフォルダです。 URLローダーのおかげで、CDNに画像を読み込み、CDN URLをCSSバンドルファイルに埋め込むことができます。 以下からもわかるように、ファイルのアップロードとCDN URL生成はプロジェクトのビルド期間に起き、CDN URLがRobloxウェブサイトに埋め込まれるため、どのMSデプロイにも新しいCDN URLは必要ありません。

ですから、WebAppの現在のビルドとデプロイパイプラインはこのように機能しています。

利点

  • 開発者は変更をリリースするのにウェブサーバーをデプロイする必要がありません。 管理者サイトへ行って、関連したコンポーネントの名前で最新のCDN URLをアップデートする必要があるだけです。 当社のリリースパイプラインで素晴らしい向上がありました。
  • 画像がアップロードされ、それぞれのコンポーネントでデプロイされ、CDNからサービスされます。
  • Webpackツール導入は、ウェブ全体のフロントエンドの開発環境をアップグレードし、エンジニアがES6+、 Typescriptなどへ自由に行けるようにします。

欠点

  • そのかわりに、この段階からの変換リソースサポートを失うため、当社が導入する新しいリソースのすべてがウェブリリースを経る必要があります。
  • 第一段階にあるように、どのコード複製、またはバンドル同士の依存は見分けるのが難しいです。

今後のこと

大きな前進をしましたが、バンドル間の依存の問題を解決するために、これからもWebpackやその他の利用可能なツールを研究し続けます。 また、当社の変換リソースフェッチは、どんな新しいリソース名前空間にも個別のデプロイを有効化して動的に取りに行ける必要があります。 当社は大きく前進しましたが、常にビルドパイプラインを速くして、開発しやすいようにする新しい機会を探しています。


Robloxコーポレーションとこのブログは、いかなる企業もサービスも推奨も支持もしません。 また、このブログに含まれる情報の正確さや完全性について、いかなる保証または約束もしません。

このブログ記事は、元はRobloxテックブログ に掲載されたものです。