Demo: "Configuring an already-compiled, static javascript single-page-app using environment variables"
Requires Docker & Docker compose. The first time you call docker compose
, it
will build the image.
git clone https://github.com/vovimayhem/env-vars-to-js-spa-demo.git \
&& cd env-vars-to-js-spa-demo \
&& docker compose up staging
Once it's running, visit http://localhost:3000 to see the app running.
This app is just a simple hello world VueJS app. The name of the person the app
is "saluting" is configured using the VITE_APP_SALUTE_NAME
environment
variable, which defaults to "Francis" in the docker compose configuration.
You can override the default by creating a new .env
file at the root of this
project, with the following contents:
VITE_APP_SALUTE_NAME=Leonidas
Once you've created this file, bring up the compose stack again:
docker compose up --force-recreate staging
The two main problems requiring solving:
- Making the app read from a javascript global object -
window
being the most suitable. - Manipulating the index.html so that it defines the variables inside the
window
object, both on "development" mode, as in "production" mode.
Take a look at the index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
<script>
window.VITE_APP_SALUTE_NAME = "<%= VITE_APP_SALUTE_NAME %>";
</script>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
Notice the script
tag. This is where we'll put the environment variables into
the window
global object... notice also the <%= VITE_APP_SALUTE_NAME %>
tag,
which is a placeholder for our real environment variables.
The HomeView.vue
file uses the window
object to get the salute to render:
const { VITE_APP_SALUTE_NAME } = window;
<HelloWorld :name="VITE_APP_SALUTE_NAME" />
This was where I got stuck the most. There's a vite plugin "vite-plugin-html-env" that I originally wanted to use, but didn't work, so I ended up doing my own plugin instead - you can check it out at "my-own-damn-html-env-plugin.js".
This plugin will replace the <%= VITE_APP_SALUTE_NAME %>
tag with the actual
value of the VITE_APP_SALUTE_NAME
environment variable when the development
server starts, and when the app gets compiled into it's final form, which
happens when building the final image:
# Notice the escaped "$" sign:
ENV VITE_APP_SALUTE_NAME="\$VITE_APP_SALUTE_NAME"
COPY --chown=${DEVELOPER_UID} . /workspaces/env-vars-to-js-spa-demo/
RUN yarn build
The process-index-html.sh
file leverages the fact that
the official nginx image contains the envsubst
command, and that scripts can be copied
to it to run before the actual nginx process starts. It is copied in the last stage
on the Dockerfile:
COPY process-index-html.sh /docker-entrypoint.d/40-process-index-html.sh
This script interpolates the environment variables into the index.html
file.
Using Visual Studio with Remote Containers extension is recommended.
Run:
docker compose up -d development
Edit with your favorite editor.
With the "Remote Containers" extension, open the cloned folder with Visual Studio Code. You'll be prompted to reopen the folder to develop in a container - choose "Reopen in Container".
Once everything is set up, run the following command, in a new VSCode terminal:
yarn dev
Edit away :)
The staging
service defined in the docker-compose.yml
file has the configuration
required to