Deploying frontend apps in storage services
In my opinion, the simplest way to deploy static frontend applications is using a storage service. In fact, it’s easy to find several posts and documentation on how to upload our code, set up a DNS and even solve routing conflicts if you are building an SPA with frameworks like Angular or React. Down here you have some of theme:
- Use S3 and CloudFront to host Static Single Page Apps (SPAs) with HTTPs and www-redirects. Also covers deployments.
- How to host static React apps in the Google Storage Bucket behind Cloudflare CDN.
- Deploy an Angular with S3 and CloudFront.
- React Router on a Nested S3 Bucket.
- Deploying frontends to Azure.
However, there is one aspect of the deployment process that most of these posts do not talk about: versioning.
You probably implement versioning during the development process using SemVer and already have named releases, but also probably you do not have the bundle of each release stored somewhere else as most of the documentation around deployments suggest using the root of the storage service to upload our files.
If a rollback is needed, we would need to go back to the release commit and rebuild our bundle and after that repeat the deployment.
During this complex and error-prone process, you will also need to make sure that the secret values (usually found in a .env file) are the same ones that were used in the previous deployment.
Multiple builds in the same storage
The best way we found to solve this and really guarantee immutability in our deployments is to redefine how we structure our app in the storage service. Instead of using the root folder of the storage as a target of our app we have one folder for each version we ever built, and apart from that we also have named folders for each one of our environments.
Using AWS S3, our root folder would look like this:
With this simple approach we can accomplish a rollback in an extremely simple process that can be done in the UI of the storage service provider: duplicate the folder of the version we need to deploy and replace the folder of the desired environment with the new one.
We also guarantee immutability and no longer need several storage accounts for a single project, all ours environments are in the same one now.
The deployment process changes a little bit as we now need to upload the content of our build to 2 folders: the version and the environment. Here is an example script that shows how we deploy our react app to AWS S3.
The main disadvantage here is configuration because now we use a relative path as the base for our app: for example “production”.
How to solve that? The easiest way is having a dedicated CDN for each environment that uses the corresponding folder as source. Although this may seem an overkill, the setup is really simple and the costs remain low. If this is not an option, configuration can also be done by properly setting the html base tag according to the environment.