LoginSignup
5
3

More than 1 year has passed since last update.

AWS CodeBuildを使ってSPAのフロント側を強制リロードする

Last updated at Posted at 2023-01-18

やりたいこと

  • フロントエンド側をデプロイした後に、画面を開き続けてるユーザを強制的にリロードさせたい
  • バージョン管理はできるだけ自動化したい

作ったもの

  1. AWS CodeBuildのbuldspec.yml
    • 自動でバージョンを採番する
    • バージョンをビルドしたモジュールに埋め込む
    • 最新のバージョン情報をAWS S3にファイルとして保存する
  2. バージョンを比較するAWS Lambda
  3. 強制リロードするフロントエンド

Image from Gyazo

AWS CodeBuildのbuldspec.yml

${CODEBUILD_RESOLVED_SOURCE_VERSION}でCodeBuildが把握しているソースのバージョンを取得できます。(詳細
それを使って、./src/version.jsを置換しています。

  build:
    commands:
      - sed -i -e "s/CODEBUILD_RESOLVED_SOURCE_VERSION/${CODEBUILD_RESOLVED_SOURCE_VERSION}/g" ./src/version.js
      - cat ./src/version.js

AWS S3に${CODEBUILD_RESOLVED_SOURCE_VERSION}の出力結果を配置しています。

  post_build:
    commands:
      - echo ${CODEBUILD_RESOLVED_SOURCE_VERSION} > version
      - aws s3 cp ./version s3://${S3_BUCKET_NAME}/ --acl bucket-owner-full-control

バージョンを比較するAWS Lambda

S3とクエリで指定されたバージョンとの比較をしています。その結果を返します。
このLambdaはクライアント端末から実行されるので、外部アクセスを許可するようにします。

    bucket = s3.Bucket(backet_name)
    obj = bucket.Object(OBJECT_KEY_NAME)
    response = obj.get()    
    body = response['Body'].read()

    if event['queryStringParameters']['version'] == body:

全文

import json
import datetime
import boto3

# バケット名,オブジェクト名
STG_BUCKET_NAME = 'frontend-stg-source'
PRO_BUCKET_NAME = 'frontend-pro-source'
OBJECT_KEY_NAME = 'version'

s3 = boto3.resource('s3')

def lambda_handler(event, context):
    print(event['queryStringParameters'])
    bucket_name = ''
    
    # バリデーションチェック
    if not 'queryStringParameters' in event.keys():
        return {
            'statusCode': 400,
            'body': 'not parameter key'
        }

    # 環境を指定されているか確認
    if not 'env' in event['queryStringParameters'].keys():
        return {
            'statusCode': 400,
            'body': 'not env parameter key'
        }
    
    # パラメータチェック
    if not 'version' in event['queryStringParameters'].keys():
        return {
            'statusCode': 400,
            'body': 'not version parameter key'
        }
    
    # 環境別にバケット名が違うので、バケット名を取得する
    if event['queryStringParameters']['env'] == 'staging':
        backet_name = STG_BUCKET_NAME
    elif event['queryStringParameters']['env'] == 'production':
        backet_name = PRO_BUCKET_NAME
    else:
        # 環境指定が間違っているのでエラー
        return {
            'statusCode': 400,
            'body': 'not expect env parameter key'
        }

    # S3からデータを取得します
    bucket = s3.Bucket(backet_name)
    obj = bucket.Object(OBJECT_KEY_NAME)
    
    response = obj.get()    
    body = response['Body'].read()
    body = body.decode('utf-8')
    body = body.strip()
    
    print({'client': event['queryStringParameters']['version'], 's3': body})
    if event['queryStringParameters']['version'] == body:
        return {
            'statusCode': 200,
            'body': json.dumps( "OK" )
        }
    else:
        return {
            'statusCode': 202,
            'body': json.dumps( "NG" )
        }

1. 最新バージョン出なかったらリロードするフロントエンド

以下は「URLが変わったら」という意味です。つまりページ遷移したらバージョンチェック処理が実行されます

watch(() => route, function (to, from) {

リクエストの結果がNGの場合はリロードする処理です。

    if (res.data == 'NG') location.href = location.href

全文

<script lang="ts" setup>
import {watch} from 'vue'
import {useRoute} from "vue-router";
import * as Version from "@/version"
import axios from 'axios'
const route = useRoute()
watch(() => route, function (to, from) {
  const request = axios.create({
    timeout: 9000
  })

  request({
    url: 'https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws',
    method: "get",
    params: {
      version: Version.Version,
      env: import.meta.env.VITE_ENV
    }
  })
  .then((res) => {
    console.log("バージョン確認:" + res.data)
    if (res.data == 'NG') location.href = location.href
  })
  .catch((error) => {
    console.log(error)
  })
}, {deep: true})
</script>

ちなみに。version.jsの中身

以下一文だけです。CODEBUILD_RESOLVED_SOURCE_VERSIONはbuildspec.ymlでsedを使って書き換えられます。importしたjavascriptで定義済みの定数が使えます。

export const Version = "CODEBUILD_RESOLVED_SOURCE_VERSION"

これで、CodeBuildを使ってデブロイされたら、自動でソースバージョンが保管されて、ページ遷移するたびに呼ばれるチェック処理によって、NGの場合は自動更新されるようになりました。

5
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
3