I have a react/node app that I'm deploying. One of the components attempts to access NODE_ENV in order to determine which host URL to use (localhost or heroku).
I now realize that even though NODE_ENV is being set to production, it's always 'undefined' in the browser context, because the environment is not node.
Since I can't access NODE_ENV from my react component, how do I dynamically set the host server?
I think you're misunderstanding the scope here. Node is a javascript runtime which runs as a server to handle backend stuff. NODE_ENV is a variable used in node to set up environment variables, thus, it is only accessible in the node environment, not in the client side.
Anyway in the first place, there is no reason why you would want to expose your config variables to your client side (that is a vulnerability issue). If it is related to some configs that relies on your server side variables, you have to set it in your client side independently. A use case I can imagine is defining a socket host and port to listen from the client side to the server side. Hope that clears things up :)
Imagine the life cycle:
You could check NODE_ENV in index.html by using:
When index.html is compiled in a production environment it will look something like this
It's a good practice to use
NODE_ENV
variables for things like API URL.If you used create-react-app, all environment variables starting with
REACT_APP_
should already be accessible withprocess.env.REACT_APP_VARIABLE_NAME
.You can try
REACT_APP_TEST=5 npm start
thenconsole.log(process.env.REACT_APP_TEST)
.If you are not using
create-react-app
, you have to import them in your webpack config.You can also choose to define the
process.env
variables for the app through a.env
file using dotenv.Yup, absolutely!
There's a difference here between having stuff around at build time, and at runtime. You'll have
NODE_ENV
around at buildtime - say you runwebpack
or something to build some JSX, or whatever.You won't have
NODE_ENV
around at runtime, when the user visits your site. There's no concept of environmental variables in that web browsing context.What I've done in this case is to programmatically create a file that will conditionally have the web server URL. Or even captures the
NODE_ENV
and puts the value in the application for later.As a practical example: in a React project I was on a couple years ago we autogenerated our index.html file. This was a silly little file, bringing in our
<script>
Javascript tags we require and adding a<div>
for the React app to render in. In the template language we did something like this:index.html.templ
after that file came out the other end of our build pipeline, it would look like this for our production build:
index.html
Then we just used normal DOM Javascript to grab the body element and check the attribute (then put it in a Redux store? I forget exactly).
At user visit time, we have an apparently hard-coded value of "production". But you and I know better!
Update: I forgot, there's actually two ways of doing this in Webpack itself, without using an external template tool and generating a file like I describe here!
Use the WebPack define plugin. This will essentially add another step to your transpiling phase: one that goes in and replaces a literal string with some other literal string. So
let e = "NODE_ENV"
would becomelet e = "production"
. There's a good Medium blog post about defineplugin, and it's kind of cool.There's some environmental variable support in Webpack itself. Apparently if you run webpack with
webpack --env.NODE_ENV=production
. Then... maybe you can useprocess.env.NODE_ENV
? The Webpack documentation for this feature isn't exactly clear on this