lift
lift copied to clipboard
[Static website] Build websites with environment variables
Use case:
I want to build my static website (e.g. npm run build
) and pass the serverless API URL to the static website as an environment variable.
Possible solution:
constructs:
landing:
type: static-website
path: dist
build:
script: 'npm run build'
environment:
VUE_APP_API_URL: !GetAtt HttpApi.ApiEndpoint
The build
option is optional:
- if undefined, the user has to build the website before
serverless deploy
- if set, the script will be run during
serverless deploy
(after the CloudFormation deployment, before uploading the static website to S3)
Challenge: the !GetAtt HttpApi.ApiEndpoint
would probably not be resolved by Serverless/Lift since this isn't a variable. So my example above isn't really working, yet this is probably the most common use case. How can we solve this?
As far as I can see this would work. I am basing it off the example I have for achieving this away from Lift: https://github.com/M1ke/serverless-payments/blob/master/bin/deploy-dev-front
So in this script I:
- Source the required
.env.*
file (whichsls
can do for me withuseDotEnv
declared) - Pull the API url out of the serverless outputs (which this example is doing using
GetAtt
) - Pass my
REACT_
variables to the build (which this does by repeating them inenvironment:
)
Only question is, what's the correct pattern for the API URL of
functions:
something:
... stuff ...
events:
- httpApi: '*'
the script will be run during serverless deploy (after the CloudFormation deployment, before uploading the static website to S3)
This means Cloudformation intrinsic functions (GetAtt, Ref, etc) won't be available. But maybe using Cloudformation outputs could be possible at this point as Serverless framework is making the HttpApiUrl
available as an output of the stack.
@mnapoli Have you put any time yet into implementing this? I'd be happy to hack on it but might not make sense if you're already nearly there with a branch somewhere else. If there's no work on it yet, may you point me to the file where I'd want to start digging? Guess it's some part of how serverless executes the build step and a binding to some part of that after the resources have been created
@M1ke not yet, I think there might be a few challenges:
- the main one is the resolution of CloudFormation functions (e.g.
GetAtt
), without that we cannot actually populate the variables - then, there's the question of when to build the website (probably in a "pre-deploy" step)
I think this requires a bit more thinking to be honest.
In the meantime, I would encourage to hardcode the API URL in the build script.
In your specific case (the URL will change every time) I think you should stick with the existing behavior (fetch the API URL from the outputs).
@mnapoli so in https://github.com/M1ke/serverless-payments/blob/f0bf3fd96c9fcbad403128d908bd4e1068ffa172/serverless.yml#L242 I output a set of JSON config. This leverages an additional plugin but possibly Lift could bundle that? So the run order internally would look like:
- Serverless runs
- Interperets Lift code and builds CFN
- Also sets up output plugin to output a range of available values (possibly each value that each component exposes) [new feature]
- CFN executes
- Output plugin writes file
- Lift runs static build [new feature]
- Lift deploys static code
- (Optional) Lift deletes output json file [new feature]
As far as I can see that would be achievable without any complex heavy lifting, just rewiring and accepting a (short term) dependency on the output plugin. As long as CDK can generate CFN code that includes the custom Outputs
block?
It seems to me like everything can work using serverless-export-outputs
and the existing features in Lift, or am I missing something?
At the moment there are no plans to add "output exporting" features like what the serverless-export-outputs
plugin does.