DEV Community

loading...

Stop using Dotenv in your front-end

Sébastien Belzile
・1 min read

Dotenv is wonderful. It allows you to use environment variables in your code, hence separating the code from its running environment.

The problem I have with it is that it is common to see people using it in the front-end of their web application (served static files, non-SSR applications).

What is wrong with this?

Your environment becomes hard-coded in your files at build time. If you proceed this way, you need to build your application every time you wish to deploy it.

Alternative

Load your configuration at runtime. This way, your CI and your CD become 2 independent components. You build only once as opposed to once per deployment. Furthermore, the same artifact is being deployed everywhere, saving you a couple build minutes, and increasing your confidence in what you are deploying.

Implementation example

In your index.html file, add a setting file that contains your environment variables:

<script src="./settings/settings.js"></script>
// must be placed before your js files
Enter fullscreen mode Exit fullscreen mode

File content example:

var environment = {
  "backendBaseUrl": "http://localhost:8000",
}
Enter fullscreen mode Exit fullscreen mode

Using Typescript? Type it:

type Environment = {
  backendBaseUrl: string
}

declare global {
  const environment: Environment
}
Enter fullscreen mode Exit fullscreen mode

Then use it:

const url = `${environment.backendBaseUrl}/potato`
Enter fullscreen mode Exit fullscreen mode

Your deployment pipeline simply needs to ensure this file is being generated/deployed, which is way faster than building your whole codebase.

Discussion (2)

Collapse
sirseanofloxley profile image
Sean Allin Newell

How would you deploy just one file separately from the SPA that the SPA imports in a typical CI/CD pipeline? Would love to see a sample repo with either CircleCI/GithubActions/Netlify set up with a bundler like webpack/parcel/esbuild to demo this decoupling.

Collapse
sbelzile profile image
Sébastien Belzile Author

Usually, in these cases, your bundler will output its results to a specific folder, ex: dist, www, out, etc.

The minimum you need is a command that takes a file from one place and copies it there:

cp config/prod.json dist/settings/environment.json
Enter fullscreen mode Exit fullscreen mode

Then, you can deploy the resulting folder.

Usually, in a CI/CD environment, you will want to set the content of these files to some CI/CD environment variables. In these cases, you may use something like envsubst or its node equivalent envsub.

Example of this (docker environment, files served by nginx)

entrypoint.sh:

#!/bin/sh
set -e

envsubst < /var/www/html/settings/settings.template.js > /var/www/html/settings/settings.js

exec nginx -g "daemon off;"
Enter fullscreen mode Exit fullscreen mode

Dockerfile:

[...]
COPY client/public/settings/settings.template.js usr/share/nginx/html/settings/settings.template.js
COPY client/config/entrypoint.sh /opt/entrypoint.sh
[...]
ENTRYPOINT ["sh", "/opt/entrypoint.sh"]
Enter fullscreen mode Exit fullscreen mode