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?
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 with process.env.REACT_APP_VARIABLE_NAME
.
You can try REACT_APP_TEST=5 npm start
then console.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.
One of the components attempts to access NODE_ENV in order to determine which host URL to use (localhost or heroku).
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 run webpack
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
<html><body ENVIRONMENT="$NODE_ENV"></body></html>
after that file came out the other end of our build pipeline, it would look like this for our production build:
index.html
<html><body ENVIRONMENT="PRODUCTION"></body></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 become let 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 use process.env.NODE_ENV
? The Webpack documentation for this feature isn't exactly clear on this
You could check NODE_ENV in index.html by using:
if ("%NODE_ENV%" === "production") {
// ...do production stuff
} else {
// ...do development stuff
}
When index.html is compiled in a production environment it will look something like this
if ("production" === "production") {
// ...do production stuff
} else {
// ...do development stuff
}
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:
- client requests
- node server processes and responds to request
- response is served through the browser