-
Notifications
You must be signed in to change notification settings - Fork 73
v1 Dotenv
dotenv
is a common way to manage environment variables in your local environment. It is preinstalled in the starter kit, and loaded for the server files in server/utils/config.js
. To use it, create a file named .env
in the root directory. This file will contain the extra environment variables that you want dotenv
to load, for example:
DATABASE_URL=postgres://postgres:opensesame@localhost:5432/cyf # see https://github.com/textbook/starter-kit/wiki/Dev-setup#databases
LOG_LEVEL=debug
If needed, you can add properties to the object exported from server/utils/config.js
for your other server files to use.
⚠️ Noteprocess.env.<THING>
should appear only inserver/utils/config.js
, to make it clear what configuration is coming from the environment. Any other parts of your app that need configuration can then import it from that single place.
If you're coming from Create React App and have got used to the custom environment variables feature, you can do this yourself with Webpack's DefinePlugin
. Note that per my blog post, however, I would generally recommend run time rather than build time configuration wherever possible.
To load the environment variables into your client code, make the following changes to ./client/webpack/common.config.js
:
const HtmlWebpackPlugin = require("html-webpack-plugin");
// add these two requires
const { DefinePlugin } = require("webpack");
require("dotenv").config();
module.exports = {
...,
plugins: [
new HtmlWebpackPlugin({ ... }),
// add this plugin with any env vars you want to define
new DefinePlugin({
// "process.env.<NAME_IN_APP>": JSON.stringify(process.env.<DOTENV_FILE_NAME>),
"process.env.APP_VERSION": JSON.stringify(process.env.APP_VERSION),
...,
}),
],
};
⚠️ Note that this is simple text substitution, only the literal textprocess.env.APP_VERSION
gets replaced with the value. If you had e.g.const envVars = process.env
thenenvVars.APP_VERSION
, that wouldn't work. See e.g. https://stackoverflow.com/a/76440819/3001761.
You can still use the REACT_APP_
(or another prefix) convention if you want to, and if you want a more automated loading of some set of environment variables you could borrow from CRA's implementation, e.g.:
const prefix = "REACT_APP_";
const varsToDefine = Object
.entries(process.env)
.filter(([key]) => key.startsWith(prefix))
.reduce((env, [key, value]) => ({
...env,
[`process.env.${key.slice(prefix.length)}`]: JSON.stringify(value),
}), {});
Now any env var prefixed with REACT_APP_
in your dotenv
file (e.g. REACT_APP_CLIENT_KEY=123
) will be available in your client code without that prefix (e.g. process.env.CLIENT_KEY
). You can tweak this recipe as needed.
⚠️ Note if you do the automatic loading you must use a prefix to distinguish the env vars that should be part of the client build from everything else available in the build environment. Otherwise you can end up leaking credentials (embarrassing example of this from ABC).
Note that the .env
file is only for local development. You'll also need to set those environment variables wherever you're building the app for production, e.g. in the standard setup:
-
Render: https://render.com/docs/configure-environment-variables
-
Heroku: https://devcenter.heroku.com/articles/config-vars (Heroku rebuilds the app from the commit content)
Note that Heroku doesn't rebuild the slug when you update environment variables, so you need to push a new commit for any changes to take effect (see e.g. https://stackoverflow.com/q/9713183/3001761).