フロントエンドのテスト環境を作った

概要

フロントエンド(SPA)のQA環境を AWS CloudFront + CloudFront Function + S3 で作成した話。

なぜフロントエンドのQA環境用にあらたな仕組みをつくったのか

フレームワークの移行作業により、多数のフロントエンド改修が走っていたが、バックエンドも含めたQA環境の数がすくなく、QAスケジュールに難が出てきたため。

また、今後もフロントエンドのみの改修案件が定常的に発生しそうだったため。

上記のような背景から、バックエンドを共有したフロントエンドのみのQA環境を多数用意できる必要が出てきたため。

前提

もともとフロントエンドとバックエンドが同一ドメインでホストされている環境。

フロントエンドはSPAであり、初期画面のHTMLだけバックエンドが生成している。

やったこと

AWS CloudFront とS3により、 任意のサブドメインでSPAだけホスティングできるようにした。

具体的な内容

フロントエンド側にて、バックエンドのアクセス先を指定できるようにした。

フレームワークの移行中だったので、内部で新旧フレームワークがそれぞれ別のhttp Clientを利用しており、どのhttpClientに対してもバックエンドのアクセス先をうまく指定する必要があった。

具体的には axios, kyなどが使われていたので、

axios.defaults.baseURL の設定をしたり、httpClientの get , post, delete などの methodにて、 new URL(originalUrl, バックエンドドメイン) を設定したり、

クロスオリジンになるので withCredentials: truecredentials: "include" を設定したり。

CORS対応

もともと同一ドメインでホストされているのでCORSの設定は得にしていなかったが、 フロントエンドを任意サブドメインでホストさせる都合でオリジンが異なる状況となったので CORSの設定を追加した。

具体的には前段にあるnginxに設定を追加している。

このような感じのもの

set $cors "";
if ( $host ~ "\.front-staging\.example\.com$"){
  set $cors "true";
}
if ($cors = "true"){
 set_header Access-Control-Allow-Origin  $origin;
 set_header Access-Control-Allow-Method "GET, POST, PUT, DELETE, OPTIONS";
 set_header Access-Control-Allow-Headers "Content-Type, X-xxx-xxx .... Authorization";
 set_header Access-Control-Allow-Credentials "true";
}

CloudFrontとS3の用意

インフラはInfrastructure as Codeで用意している(AWS CDK (cloudformation)利用)

基本的には普通に作る。

通常と違うのは下記2点

  • CloudFrontで *.front-staging.example.comのように任意サブドメインのリクエストを受け入れるように設定
  • CloudFront Functionにて、 オリジンリクエストを //path/to/file に書き換えるよう設定

このような雰囲気のシンプルなCloudFront Functionを利用した

function handler(event) {
  var pathPrefix = event.request.headers.host.split(".")[0];
  event.request.uri = pathPrefix + event.request.uri;
  return request;
}

CloudFrontFunctionは ES5.1らしく、letやconstすら使えない世界。

S3には、1か月ファイルが消えるLifeCycle Policyが設定されている。*1

CI 環境の整備

PullRequestに対して、 SPAをビルドし、ビルドした成果物を s3の /PR-ID/path/to/file に置き、 https://PR-ID.front-staging.example.com を通知する。というCI Jobを作成した。

まとめ

上記では全く触れていないが、当初は GitLab の GitLab Pagesにある、 Job Artifactsを ブラウザで見られる機能を利用しようとしてスタートした。

断念した理由として、 GitLab PagesのJob Artifactsのブラウジングでは / で終わるURLに対して、 /index.html を呼んでくれない。 そもそも Pathにprefixがつくため、rootでホストされることが前提に作られているSPAと相性がわるい。

という話があり、途中で CloudFrontを利用する方向に舵を切りなおしている。

結果的に、それなりに使えるものが出来上がったので良かった。

そもそも最初からVercelのようなサービスを使えばいいのはそうなのだが、

現状Vercelの利用実績がないため、導入には社内でのセキュリティチェックや決済を通す必要があり、ハードルが高かった。

AWSであればプロダクション利用しており、CloudFrontとS3の値段程度は誤差なので、改めて決済する必要もなく、スムーズに利用できた。という背景がある。

*1:実際にはもっと短くてもよいが、ファイルサイズ的に保管にかかる金額は考えなくていい程度であるため、長すぎない程度の適当長さを設定している。