¿Es posible ejecutar un comando de compilación externo como parte de una secuencia de pila de CDK? Intención: 1) crear una API de reposo, 2) escribir la URL de reposo en el archivo de configuración, 3) compilar e implementar una aplicación React:
import apigateway = require('@aws-cdk/aws-apigateway'); import cdk = require('@aws-cdk/core'); import fs = require('fs') import s3deployment = require('@aws-cdk/aws-s3-deployment'); export class MyStack extends cdk.Stack { const restApi = new apigateway.RestApi(this, ..); fs.writeFile('src/app-config.json', JSON.stringify({ "api": restApi.deploymentStage.urlForPath('/myResource') })) // TODO locally run 'npm run build', create 'build' folder incl rest api config const websiteBucket = new s3.Bucket(this, ..) new s3deployment.BucketDeployment(this, .. { sources: [s3deployment.Source.asset('build')], destinationBucket: websiteBucket }) }Desafortunadamente, no es posible, ya que las referencias necesarias solo están disponibles después de la implementación y, por lo tanto, después de intentar escribir el archivo (el archivo contendrá tokens cdk ).
Personalmente, resolví este problema diciéndole a cdk que envíe las URL de apigateway a un archivo y luego las analice después de la implementación para cargarlas en un depósito S3, para hacerlo necesita:
cdk deploy -O ./cdk.out/deploy-output.json./cdk.out/deploy-output.json encontrará un objeto JSON con una clave para cada pila que produjo una salida (por ejemplo, su pila que contiene una puerta de enlace API) Por supuesto, tiene los últimos pasos en un script personalizado, lo que significa que debe envolver su cdk deploy . Sugiero hacerlo con un script de nodejs, de modo que pueda aprovechar aws-sdk para cargar su archivo en S3 fácilmente.
Aceptando que cdk no admite esto, dividí la lógica en dos scripts de cdk, accedí a la URL de la puerta de enlace API como salida de cdk a través de la cli, luego envolví todo en un script bash.
CDK de AWS:
// API gateway const api = new apigateway.RestApi(this, 'my-api', ..) // output url const myResourceURL = api.deploymentStage.urlForPath('/myResource'); new cdk.CfnOutput(this, 'MyRestURL', { value: myResourceURL });Intento:
# deploy api gw cdk deploy --app (..) # read url via cli with --query export rest_url=`aws cloudformation describe-stacks --stack-name (..) --query "Stacks[0].Outputs[?OutputKey=='MyRestURL'].OutputValue" --output text` # configure React app echo "{ \"api\" : { \"invokeUrl\" : \"$rest_url\" } }" > src/app-config.json # build React app with url npm run build # run second cdk app to deploy React built output folder cdk deploy --app (..)¿Hay una mejor manera?
Como han mencionado otros, esto no es compatible con CDK. Así lo solucionamos en SST: https://github.com/serverless-stack/serverless-stack
En el lado de CDK, permita definir variables de entorno de React utilizando los resultados de otras construcciones.
// Create a React.js app const site = new sst.ReactStaticSite(this, "Site", { path: "frontend", environment: { // Pass in the API endpoint to our app REACT_APP_API_URL: api.url, }, });Escupa un archivo de configuración mientras inicia el entorno local para el backend.
Luego inicie React usando sst-env -- react-scripts start , donde tenemosuna CLI simple que lee el archivo de configuración y los carga como variables de entorno de tiempo de compilación en React.
Durante la implementación, reemplace estas variables de entorno dentro de un recurso personalizado basado en los resultados.
Escribimos sobre esto aquí: https://serverless-stack.com/chapters/setting-serverless-environments-variables-in-a-react-app.html
Y aquí está la fuente de las construcciones ReactStaticSite y StaticSite como referencia.