システム構成図
システム構成
- ReactのソースコードはS3 Backetにアップロード
- BacketはCloudFrontを経由して公開する
- ステージング環境と本番環境がある
やりたいこと
残念ながらCIは導入されていないので、手動でデプロイする必要がある
ステージング環境と本番環境へのデプロイをできるだけ簡素化したい
これまで手動でやってたこと
- APIの向き先を変更して
npm run build
- 該当S3バケットにbuildしたファイルをアップロード
- CloudFrontのキャッシュを無効化
- これをproductionとstaging で実施
ひとつずつスクリプト化していく!
これまで手動でやってたこと
- APIの向き先を変更して
npm run build
- 該当S3バケットにbuildしたファイルをアップロード
- CloudFrontのキャッシュを無効化
- これをproductionとstaging で実施
Reactのbuild時に.envファイルを切り替える
- npm-scriptsにprebuildを定義して、そこで.envファイルを差し替え
- で、postbuildで元に戻す
まぁ 動いた
env-cmd
あとで公式ドキュメント見てたら、そのものズバリの記載があった
Deployment · Create React App
Customizing Environment Variables for Arbitrary Build Environments
(任意のビルド環境用の環境変数のカスタマイズ)
For example, to create a build environment for a staging environment:
どう使う?
package.json
{
"scripts": {
"build": "react-scripts build",
"build:staging": "env-cmd .env.staging npm run build"
}
}
これまで手動でやってたこと
- APIの向き先を変更して
npm run build
- 該当S3バケットにbuildしたファイルをアップロード
- CloudFrontのキャッシュを無効化
- これをproductionとstaging で実施
Amazon S3へのファイルのアップロード
- AWS SDKでアップロード
async function putFile(sourceFile) {
// S3にputするファイル名
const dir = process.env.DIRECTORY ? `${process.env.DIRECTORY}/` : '';
const key = sourceFile.replace('build/', dir);
// ファイルの内容を取得
const data = await fs.readFile(sourceFile);
const params = {
Bucket: process.env.BUCKET,
Key: key,
Body: data,
ContentType: mime.lookup(sourceFile),
};
await s3.putObject(params).promise();
debug(`putObject: ${key}`);
}
これまで手動でやってたこと
- APIの向き先を変更して
npm run build
- 該当S3バケットにbuildしたファイルをアップロード
- CloudFrontのキャッシュを無効化
- これをproductionとstaging で実施
CloudFrontのキャッシュ無効化
deploy.js
const cloudFront = new aws.CloudFront();
await cloudFront.createInvalidation({
DistributionId: process.env.DistributionId,
InvalidationBatch: {
CallerReference: uuid(),
Paths: {
Quantity: 1,
Items: ['/*'],
}
}
}).promise();
これまで手動でやってたこと
- APIの向き先を変更して
npm run build
- 該当S3バケットにbuildしたファイルをアップロード
- CloudFrontのキャッシュを無効化
- これをproductionとstaging で実施
環境変数をいい感じに切り替える
dotenv
Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env.
.env.production
と .env.staging
をnpm-scriptsで呼び分ける
どう使う?
deploy.js
// 環境変数TARGETを元に読み込むファイルを切り替え
const target = process.env.TARGET || 'production';
require('dotenv').config({
path: `${process.cwd()}/.env.${target}`,
});
package.json
{
"scripts": {
"deploy": "node scripts/deploy.js",
"deploy:staging": "TARGET=staging npm run deploy"
}
}
まとめ
ec2のWebAPI更新が手動なので、これもnpm-scriptsから更新がキックできたらいいな