Current section: Scripting 7 exercises

Environment Variables for Client-Side and Server-Side


00:00 For this exercise, there are a couple of things that I need to give you some background on for you to be successful. First of all, I'll say that the primary learning outcome of this exercise is pretty simple. You're simply going to add a script tag and properly set the inner HTML for that, so you can have some dynamic script running in here.

00:19 But there are a couple of things that, for the particular use case we're going to use that for, where you need to understand a few things. So first of all, Remix has actually two builds. And in fact, we actually have three builds in here. So our first build is this server build.

00:33 That's taking our server index.ts file and converting it into a JavaScript file right here. So that's us. That's all managed by this build server file that we have. That's actually not super relevant for this exercise,

00:49 but I thought it's important for you to understand that aspect for our particular app. The other thing, as far as Remix is concerned, we have two builds. So we have this bundle, this index.js. This is all of our server-side code.

01:05 Everything that matters as far as the server is concerned, that's showing up right here. And then we have our client-side code. That is all the stuff that's going on in here. So we've got all these different JavaScript files that are being built, and then Remix is managing getting those onto the page when they're supposed to.

01:23 So both of these will have our React components and everything built in there, but Remix intelligently splits the different pieces, like loaders go into the server build but not in the client build, stuff like that. So that's one thing that you need to understand about that.

01:40 And for each of these, they have an entry, so the first file that shows up for these. The server has this entry. It's called entry.server in the app directory. And so Remix will actually resolve all of the files that are imported by the server,

01:58 as well as those inside of our routes conventionally, all the routes that we create. And then for the client build, it starts with the entry.client. And so Remix will point its build tool at the entry.client, and then it will resolve all dependencies, including our routes based on the convention.

02:18 So with that, if there was any code that you wanted to run on the client, you could do that in the entry.client. Any code you want running on the server, you do it on the entry.server. Now let's talk about another piece of background that you need to know for this exercise, and that is our environment variables.

02:36 So here on the entry.server, we have this getenv. So this is inside of the env server, and we have all the environment variables that we're going to have in our application are loaded in here. We define what those are based on this required server environment variables,

02:56 and we validate that those environment variables are set up so we can have some autocomplete. So with that, we say processenv. and then we get our autocomplete there. So that's what all of this is doing, not something that you need to really necessarily learn so that you can implement it over and over again. And so that's why I did it for you.

03:14 You can just reference this anytime you need to do that, which is not very often. But then we're also doing the same thing for our global environment, or for our window browser environment as well. And so we can say window.env. and now we have mode.

03:31 And so everything that's returned by getenv will be accessible on a global environment under the all caps env flag. So what you're going to be doing is actually making this possible,

03:46 making it so I can say all caps env and then .mode and have some autocomplete and everything here. So the env.server file itself will be done. It is already done for you. But you are responsible for making it so that those variables,

04:04 those environment variables are accessible in the client on window. So that's the script that you're going to be implementing. Now the reason why this may be a little more tricky than you might have experience with in the past

04:18 is because other build tools at build time would make process.env accessible so that you can use any process.env in any component that you so choose.

04:30 So you could go into this component and just say console.log process.env.whatever and you're off to the races and everything's good. This is not a good thing because this code goes to the client.

04:48 So you would definitely not want process.env available there. The build tools kind of fake it because they process this value at build time and then they'll replace it with whatever the value is at build time. And so that sort of works.

05:05 But in the Remix world, this is all happening at runtime. And so you will not have access to process.env in the browser. And so part of what your job is is to make the variables that we want to have accessible,

05:19 specifically those that are returned by this get.env, make those accessible on the client and to make it so that they will be accessible in the same way on both the client and the server.

05:32 So the way this env.server is set up makes it so that TypeScript is good with you saying env.mode and you can console.log this. And even though this will run both on the server and the client, we will set things up in such a way that this will work in both of those environments,

05:51 this exact same code. So the server side of this is already done for you. That's this global.env equals get.env. So we're setting the global.env variable. But again, this is the entry server. You need to make this work on the client.

06:04 And you can't just say window.env equals get.env right here because the get.env is accessing process.env. So get.env is only accessible on the server. Additionally, we couldn't even import this env.server because we're in a client file

06:24 and everything that's in a .server is only accessible on the server. So we have to have some mechanism for getting that stuff that's on the server into the client. And that is what you're going to be doing in this exercise. So hopefully with all of that background,

06:42 that gives you an idea of what our objective is for this exercise and what our constraints are and why it's actually a really good thing that we have this set up the way that we do. So when you're all finished, you are actually going to be using that env.mode

06:59 to determine whether or not to dynamically import some DevTools. And so when that is all done, you should get a log to the console showing that the DevTools have been installed. With all that said, I think that you're ready to go. And the emoji will guide you. The instructions will be there to guide you as you get through this.

07:17 And then I'll see you on the other side of the exercise and I'll implement it with you. See ya.