Environment Variables in React Bundles
Get the project source code below, and follow along with the lesson material.
Download Project Source CodeTo set up the project on your local machine, please follow the directions provided in the README.md
file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.
Lesson Transcript
[00:00 - 00:08] In this module, we're going to talk about how frontend.end is a little bit different from backend.end. So why do we even need a separate module for this?
[00:09 - 00:13] Well, for three main reasons. Firstly, security.
[00:14 - 00:18] Nothing on the frontend is a secret. Not even if it's obfuscated or encrypted.
[00:19 - 00:36] Number two, bundling means updating your configuration is slow, so you can't even see the config changes until after you deploy. Number three, the component programming hierarchy means that frontend needs a higher preference for reusability.
[00:37 - 00:52] So to reduce coupling, you have to avoid using environment variables directly or passing from state, and instead you have to pass values from a config object or from the parent. When then do you even need to configure the frontend?
[00:53 - 01:13] Well, for example, switching between resources during development, such as databases and payment IDs, or toggling dev only or prod only resources, such as logging for dev and analytics for prod. But what if you need to change the configuration quickly on your frontend?
[01:14 - 01:22] Use feature flags. For those who don't know, a feature flag is when you use a database to toggle when and who should have access to a feature.
[01:23 - 01:39] It can be used for testing experimental features such as AB testing or for enabling features for specific users. The most common feature flag service is launched darkly, but I recommend trying it out on a freemium provider such as Posthog.
[01:40 - 01:57] This technically outside the scope of this course, so I'm just brushing over it , but let me know if you want me to expand on this anyways. For reference on when and where to configure your frontend, I've set up an example chart in the description because I'd rather get right to the demo instead of reading off lists.
[01:58 - 02:04] So let's dive right into it. In this demo, I'll be toggling a logger in React using environment variables.
[02:05 - 02:12] We have here a create react app, and it's clean. We have nothing so far to it.
[02:13 - 02:29] And what we'll do to start with is install our log level package. Now that we've installed log level, we'll initialize the log level library in index.js.
[02:30 - 02:46] There's two settings that we can do for log level, silent and trace. So now we'll set the default to be silent, but ultimately this value needs to be set by our environment variables.
[02:47 - 02:54] To do that, we're going to create a .n file. Our .n file will be used to set default.
[02:55 - 03:02] And one thing you'll note is I haven't had to install .n. That's because it's built into the React Scripts tool chain.
[03:03 - 03:11] These front-end frameworks these days also have this functionality built into their CLIs, including view. The .n flow strategies are also built into this.
[03:12 - 03:27] That is, you can use star local, and there's a proper emerging strategy. It can be okay to commit certain .n files into Git as long as you're pushing settings that are instance-unspecific, such as log levels.
[03:28 - 03:47] No server URLs, you should be handling this through a .n cloud provider. Once again, no credentials or unique end-to-end fires in Git, only settings because everything is exposed to the users from front-end and Git is also vulnerable to exposure.
[03:48 - 03:58] So we're going to add the log level to the .n. Again, this is our default, so we'll say equals silent.
[03:59 - 04:26] But React will only inject environment variables that are prefixed with React app, which is a very important security feature because it means you don't have generic environment variables from your operating system, like Java home location. By default, I'm picking silent because, which would be the production value, but I'll be overriding that value in development regardless.
[04:27 - 04:49] I also like to abstract the environment variables using a constants file. This is not mandatory, but it helps in a few ways, such as setting value defaults, auto-complete in components to avoid spelling errors and converting from strings to their appropriate types.
[04:50 - 05:11] The way I like to use the constants file is I create an empty object that I export, and then I set each of the environment variables as a value of this object. In this file, we can then set defaults, like silent, and then do any sort of type conversions as necessary.
[05:12 - 05:28] Now all that's needed to be done is go into our index.js, import the constants file, and then set the log level using that value, constants, that log level. You'll notice the auto-complete showing up.
[05:29 - 05:45] One thing I'd recommend you look out for is if this is not immediately working when you use process.n, you may actually be using Vite, which is a different script runner with React. You can check in your package.json if you see build Vite.
[05:46 - 06:06] The difference here is that you can no longer access your .n variables through React app in your .n and process.n.react app. It's actually a different way, which firstly, the variables have to be prefixed with Vite, so let's do that now.
[06:07 - 06:25] We also need to make sure that where we're referencing it, we actually, but we 'll first put Vite. Instead of using process.n, we actually do import.meta.n, and now that works.
[06:26 - 06:49] This is yet another reason why it's so important to have a constants file, because now if you're using Vite versus using React scripts, the way to reference the value may change, but you can actually just change it in one place instead of going through all of your files and changing them. So anyways, let's go and use this now.
[06:50 - 07:05] So we'll go into our app.js and we'll log a message. So let's import the log library, and then we'll log a message.
[07:06 - 07:16] And you'll notice that that message is not showing up, because we've set our log level to silent, but we don't really want to change the default. We want to just change it for development.
[07:17 - 07:31] And right now, you're using node start. One thing to note is that build always does node n equals production, start always does development, and test always does test.
[07:32 - 07:37] There's no good way to overwrite these, but this is also intentional. Don't overthink it.
[07:38 - 07:45] Keep it simple. So anyways, we'll go now and create a dot end dot development file.
[07:46 - 08:02] In here, we'll set the value of the log level to be trace. And now that we've done that, it should begin to work shortly.
[08:03 - 08:12] Now that we've set the value to trace, we can see that the log is showing up in the console. Note this is the console for the website.
[08:13 - 08:30] This is a logger for logging in the browser, not on the terminal. So now that that's working, let's make it easier for our team to also use the project by creating a dot env dot template file.
[08:31 - 08:49] So we can take what we have here. We can maybe set silent trace to be our default since all the other defaults are already silent, just so that people know roughly what's supposed to go in this file.
[08:50 - 09:03] And yeah, since dot env is built into the tool chain, we probably won't be able to use other dot env libraries, such as dot env extended. So we can't use things like schema files.
[09:04 - 09:18] Sometimes you don't want all that and you just want to be able to toggle features from node end directly. So in order to do that, let me show you how to toggle a version code based on the value of dot end.
[09:19 - 09:33] So first, let's get the value of the version from package JSON. So import the configuration, I'm going to call it node config from package dot JSON.
[09:34 - 09:48] And then we'll set the value variable as version. And we'll set a backup value to be empty string.
[09:49 - 09:59] Now all we have to do is refer to that in a paragraph tag. Okay, that's showing up now.
[10:00 - 10:12] This could be useful if you have a beta version of the site and you want your beta users to tell you which version of the site they're looking at or in development. So that way, you know how far back a bug has taken place.
[10:13 - 10:26] But you don't want this to be showing up on production. So let's make sure that only shows up when node end equals development.
[10:27 - 10:38] So it'll show app version and otherwise it'll just show an empty string. As you can see, sometimes process dot end works.
[10:39 - 10:52] Sometimes you have to use it import dot meta dot end. And there's a few different strategies that we've gone over that should work for other webpack related front ends.
[10:53 - 10:53] Thank you. See you in the next one.
This lesson preview is part of the Environment Variables for Web Developers course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.
Get unlimited access to Environment Variables for Web Developers, plus 70+ \newline books, guides and courses with the \newline Pro subscription.
![Thumbnail for the \newline course Environment Variables for Web Developers](/_next/image?url=https%3A%2F%2Fs3.amazonaws.com%2Fassets.fullstack.io%2Fn%2F20230206130455193_5.png&w=3840&q=75)