Inject environment variables into static files at runtime.
The common front-end build tools (like CRA) inject the env vars at build time. This means if we want to deploy the static files in a docker environment, we need to build a different docker image for each environment, as the URL for the server and other values that usually come from an env var will be inlined in the final bundle. This behaviour prevents the docker image to be built once and run anywhere - on any environment (dev, test, staging, prod) - just requiring us to provide the different configuration of each environment.
This project aims to feel this gap by allowing to inject environment variables into
static files at runtime using the approach mentioned at the CRA
documentation.
Another option would be to serve the application using a Node.js webserver to inject the env vars in each request. Shipator takes a different approach by trying to keep working exclusively with static files in order to leverage high-performance webservers like ngnix to serve the files while enabling us to inject env vars at runtime.
Shipator will replace a placeholder (like __ENV__
) of a targeted static file with the allowed env vars.
It ships with an official docker image that uses OpenResty
(a ngnix distribution) to serve the files. Whenever the container starts,
it will read all the env vars starting with the prefix defined at SHIPATOR_PREFIX
(default REACT_APP
),
and inject the env vars in the place of the placeholder defined at SHIPATOR_PLACEHOLDER
(default __ENV__
)
of the target file defined at SHIPATOR_TARGET
(default /app/shipator/html/index.html
).
After the replace the ngnix server will be started to serve the static files.
Note: The following example assumes that your project was generated by CRA however, all the steps can be applied to different setups given a few minor modifications.
- Update the
public/index.html
of your project, inserting the__ENV__
to be injected at runtime, but fallbacking to the build time env vars that CRA provides, so it works locally normally.
Insert the following snippet right before the </head>
closing tag.
<script>
window.ENV = (function() {
try {
return __ENV__;
} catch (e) {
return {};
}
})();
window.ENV.REACT_APP_SERVER_URL =
window.ENV.REACT_APP_SERVER_URL || '%REACT_APP_SERVER_URL%';
</script>
- Update the rest of the project to get the values from this global variable:
const baseUrl = window.ENV.REACT_APP_SERVER_URL;
- Create a Dockerfile using shipator
FROM node:12.16.1-alpine as builder
WORKDIR /app
COPY yarn.lock /app/yarn.lock
COPY package.json /app/package.json
RUN yarn install --frozen-lockfile
COPY . /app
RUN yarn build
FROM Finbits/shipator:1.0.2
COPY --from=builder /app/build /app/shipator/html
- Build the docker image.
$ docker build --rm -t my-webapp:latest .
- Start the webserver
$ docker run --rm -p 3000:80 -e REACT_APP_SERVER_URL=http://my-api.com my-webapp:latest
- Now open your browser at http://localhost:3000.
If you open your dev tools console, and write window.ENV.REACT_APP_SERVER_URL
,
it will return http://my-api.com
.
Note: If you use kubernetes in production the env vars could be placed in a configmap, with different values for each deployment environment.
You can also use the shipator CLI directly. You can download it on the releases page.
Usage
$ shipator [options] target
Options
-placeholder string
Placeholder in the target (default "__ENV__")
-prefix string
Prefix of the env vars to inject (default "REACT_APP")
-version
Prints current version
Examples
$ shipator build/index.html
$ shipator -prefix REACT_APP -placeholder __ENV__ build/index.html
$ shipator -placeholder __VARS__ build/index.html
$ shipator -prefix VUE_APP build/index.html
See the changelog.
See the contributing file.
Copyright 2021 © Finbits.
Shipator source code is released under Apache 2 License.
Check LICENSE file for more information.