はじめに
こんにちは!ギフティの石川です。
ギフティでは、ギフトを使ったマーケティングを行いたい企業様向けに購入可能なギフトを閲覧できるポータルサイトをご提供しています。
今回は、そのポータルサイトの一部をリニューアルしましたので、なぜリニューアルを行ったのかとリニューアルの際に利用した技術についてご紹介していきたいと思います。
なぜリニューアルしたのか
ギフティでは企業様がギフトの閲覧から購入までを一気通貫して行えるようなポータルサイトをご用意しています。
しかしながら、ポータルサイトを立ち上げた当初から現在にかけて少しずつビジネスモデルに変化が生じたことによって、現在のポータルサイトでは顧客体験の向上や社内の業務効率の向上に限界を感じていました。
そこで、ギフティでは思い切って現在のポータルサイトから新ポータルサイトへのリニューアルを行いました。
リニューアルサイトの構成
新ポータルの作成に当たって、バックエンドは旧ポータルサイトのものを流用し、フロントとBFF(Backends For Frontends)の二つを作成しました。
BFFを用意したのは、各アプリケーションに特化したBFFを用意することでバックエンドがより汎用的な作りにできるからです。
ギフティではバックエンドを共有したプロダクトが数多く存在します。一つ一つに特化した作りにすると別のプロダクトが影響を受けやすくなるため、できるだけ汎用的に作られています。
そこで、BFFを作成することでバックエンドに変更を加えずに、新ポータルに特化したロジックを入れ込めるようにしています。
BFFで採用した技術スタックは下記の通りです。
- TypeScript/Node.js
- Amazon API Gateway
- AWS Lambda
- Serverless Framework
本記事では、この中でもServerless Frameworkに注目してご紹介していきたいと思います。
本記事で利用したServerless Frameworkのバージョンは3.19.0です。
Serverless Frameworkとは
Serverless Frameworkは簡単にサーバーレスなリソースを作成することができるツールの一つです。AWSやAzure、GCPといった複数のクラウドベンダーが提供するサーバーレスなリソースを簡単に作成することができます。
また、複数のサーバーレスなリソースをまとめてデプロイすることもでき、管理が楽になるといった特徴もあります。
今回はこういったメリットから、Serverless Frameworkを採用しました。
Serveless Frameworkは前述の通り複数のクラウドベンダーに対応していますが、新ポータルはAWSを利用しているためAWSが提供するサーバーレスなリソースに絞ってご説明していきたいと思います。
開発者はServerless Frameworkの設定ファイルであるserverless.ts
に設定を記述し、serverless deploy -v
コマンドを打つだけでサーバーレスなリソースをデプロイすることができます。
めちゃくちゃ簡単ですね。
では、もう少しServerless Frameworkの動きを見てみます。
serverless.tsについて
前述したserverless.ts
についてご説明します。
こちらの設定ファイルはymlファイルでも書くことができます。
Serverless Frameworkではserverless.ts
に設定を少し書くだけでサーバーレスなリソースを作成してくれます。
下記がserverless.ts
の例です。
import funcitionName from '@/functions/functionName'; const serverlessConfiguration: AWS = { // service名 service: '', // Serverless Frameworkのバージョン frameworkVersion: '3', // 追加したいpluginの設定 plugins: [], provider: { // クラウドベンダー名 name: 'aws', // 実行環境 runtime: 'nodejs16.x', // stage名 stage: '', // region名 region: 'ap-northeast-1', // 作成したいiamRole iamRoleStatements: [ ], // Amazon API Gatewayの設定 apiGateway: { }, // 環境変数の設定 environment: { } }, functions: { funcitionName }, package: { individually: true }, custom: { // バンドル & トランスパイルの設定 esbuild: { bundle: true, minify: true, sourcemap: true, exclude: [], target: 'node16', define: { 'require.resolve': undefined }, platform: 'node', }, }, }; module.exports = serverlessConfiguration;
主要な要素だけをピックアップしてご説明します。
plugins: 適応したいプラグインを記述します。 Serverless Frameworkは基本的な機能のみを提供しており、各サービスに合わせてここにプラグイン記述することで機能を拡張していきます。 代表的なプラグインはローカル環境でアプリケーションを実行できるserverless-offlineなどがあります。
provider: アプリケーションを作成したいクラウドプロバイダーを記述します。今回はAWSを利用しているため”aws”と記載しています。
functions: クラウド環境上にデプロイする関数名を記述します。AWS Lambdaで動かしたいアプリケーションをこちらに記載します。
custom/esbuild: バンドルとトランスパイルの設定を記載します。今回はesbuildを使います。esbuildはwebpackと比較して高速に実行することができます。
また、Serverless Frameworkではデプロイを実行すると上記のserverless.ts
を元に.serverless
ディレクトリに下記のファイル群を作成します。
- serverless-state.json
- cloudformation-template-create-stack.json
- cloudformation-template-update-stack.json
serverless-state.json
はServerless Frameworkのdefaultの値に前述のserverless.ts
で設定した値を上書きして出力します。serverless.ts
で設定されなかった値はdefaultの値がそのまま入ります。
cloudformation-template-create-stack.json
は後述するS3を作成するために使うCloudFormationのテンプレートファイルです。
cloudformation-template-update-stack.json
はserverless-state.json
をCloudFormationのテンプレートファイルに変換したものでクラウド上に展開されるリソースが記載されています。
作成されるリソースについて
Serverless Frameworkは主に下記のリソースを作成してくれます。
- S3
- Amazon API Gateway
- AWS Lambda
一つ一つ見ていきましょう。
S3
Serverless Frameworkはzip化したアプリケーションや、CloudFormationのテンプレートファイルをS3で管理するためにS3を作成します。
具体的には下記のように作成されます。
// パス <service名>-<stage名>-serverlessdeploymentbucket-<ハッシュ値>/serverless/<service名>/<stage名>/<時刻>/ // ファイル compiled-cloudformation-template.json serverless-state.json <applicaiton名>.zip
compiled-cloudformation-template.json
はcloudformation-template-update-stack.json
と内容的には同じものでクラウド上に展開されているリソースを表すものです。このように、リソースの管理はCloudFormationがよしなにやってくれるので、開発者はリソースの管理方法を考える必要はありません。
serverless-state.json
はローカル上に作成されたserverless-state.json
のコピーです。
<applicaiton名>.zipはAWS Lambdaで動かすアプリケーションをzip化したものです。
Amazon API Gateway
ServelessFrameworkでは、下記のようなファイルを用意しserverless.ts
に読み込ませるせることでAmazon API Gatewayを作成することができます。
また、serverless.ts
やserverless.yml
にもAmazon API Gatewayの設定を書くことができるので、下記のようにファイルを分割しなくてもAmazon API Gatewayを作成することができます。
CloudFormationの形式よりもかなり直感的に記載できますね。
serverless.ts
import funcitionName from '@/functions/functionName';
index.ts
import { handlerPath } from '@/libs/handlerResolver'; export functionName = { // AWS Lambdaで動かすアプリケーションのエントリーポイント handler: "", events: [ { http: { // API Gatewayで作成するリソースに紐づくメソッド method: 'post', // CORSの設定 cors: cors, // API Gatewayに作成するリソースパス path: '/resource1', }, }, ], };
handler: Amazon API Gatewayに紐づけたいアプリケーションのエントリーポイントを記載します。
events: 上記で記載したアプリケーションをどのような時に実行するかを記載します。 例では、https://
/<stage名>/resource1にpostメソッドを送信した際にアプリケーションが実行されます。
AWS Lambda
Serveless Frameworkでは下記のようなディレクトリでAWS Lambdaで実行するアプリケーションコードを管理します。
こちらで管理しているアプリケーションのhandlerをserverless.ts
(serverless.yml
)やindex.ts
に設定しデプロイすることでAWS Lambdaが作成されます。
|- service名
| |- src
| | |- functions
| | | |- function1
| | | | |- handler.ts
| | | | |- schema.ts
新ポータルで作成したBFFはAPIにGraphQLを採用しているため、アプリケーションのhandler.ts
は下記のような実装になりました。
import { ApolloServer } from 'apollo-server-lambda'; import { schema } from '@/functionName/schema'; const server = new ApolloServer({ schema, plugins: [], }); export const handler = server.createHandler();
おわりに
今回は、新ポータルの一部リリースのお知らせと新ポータルに利用した技術であるServerless Frameworkをご紹介いたしました。 Serverless Frameworkはサーバーレスなリソースを素早く作成することができるため、おすすめの技術の一つです。 この記事がインフラ作成の活用の一助になれば幸いです。