Closed meghprkh closed 8 years ago
Can you please clarify your use case in a little more detail? I'm specifically interested in the problem you were solving (configuring for multiple quizzes?) than the exact proposed solution.
I might have one. Let's say there is api server running at different enviroments like so:
And I'm building SPA which supposed to use CORS and being hosted anywhere, just like static site.
And such I want to supply dev/prod absolute paths for different versions of SPA.
Hope this makes sense.
I think at that point you have a very advanced use case and ejecting is the way to go. I don't think adding .env
support by default is really necessary, since most users will never need it?
@mxstbr Yes may be true, but I just wanted to open this for some discussion, please feel free to close it.
I try to explain my use which is somewhat similar to @dmi3y's usage:
/quiz1
and other on /quiz2
.env.js
file so that it is accessible to the main app.Basically the .env.js
file can act as a way to preprocess any constants without having to include any file in the main app. So for example if we are going to use homepage of package.json, we can include package.json in the .env file and export the constants after a little modification also. However if we do this in the main app, it is not preprocessed and package.json will be included in the app bundle also. While not an issue here because it would be anyways minifed, it will be an issue when we have to use a node module for generating a constant and thus bundle size may increase or it may not work
This is an advanced use case but not a obtrusive solution (not needed but can be provided kind of thing).
I hope this explains clearly the purpose.
Yes may be true, but I just wanted to open this for some discussion, please feel free to close it.
Absolutely no fault in that, we're definitely not saying create-react-app
is perfect by far! Discussions like these could open our eyes to use cases we haven't though of, they're incredibly important.
I'm not sure I fully understand your use case, wouldn't you need access to the webpack config anyway if you're changing the publicPath
?
@mxstbr not as per https://github.com/facebookincubator/create-react-app/issues/21 where it would be automatically understood from package.json
's homepage
Something I missed when trying create-react-app
in a cloud9 free workspace was the ability to set a custom IP
and PORT
for the server to listen to.
I was able to achieve that by manually changing thestart
script in react-scripts
, but I think using environment variables for that would be much simpler, even more for begginers.
^ That's also my use case. I need to adjust the ip/port for usage on Cloud9.
I'm curious, can you explain how the workflow works with cloud9? Do you have the developer server running in the cloud and use their browser text editor to edit the code? Where do you see the terminal output? Why not develop locally?
I mainly use this kind of service (Cloud9, Nitrous.io, etc...) when I'm at work and don't have access to my PC.
They're also a good place to study with friends, since they allow collaborative coding. Plus, somewhere free to showcase a small app?
And yes, you use their browser text editor to edit the code and there's also a terminal emulator in the text editor.
One use case I often have for environment variables is when I want to run some code in production but not in development. For example, if you're using an analytics service, you might not want to log any analytics from development versions of the app. Or if you use an external service to sign people up for a mailing list, you don't want your test accounts getting in there.
About Cloud9, one situation I see it adopted more and more is for education. If you're teaching a class of people how to use some technology, you don't want to spend a ton of time making sure everyone has their development environment set up. If you can just give them one Cloud9 config they can get going quickly. So it would be pretty nice to support Cloud9. They also just got acquired by Amazon to be integrated into AWS, which is another sign this sort of thing is going to grow in popularity.
One use case I often have for environment variables is when I want to run some code in production but not in development.
We currently already allow this with process.env.NODE_ENV
checks. This is how React determines which code path to use.
So it would be pretty nice to support Cloud9
Absolutely agree. I just want us to learn more about different use cases first, and approach the problem holistically, rather than add flags one by one over time. A holistic solution might turn out to be simpler.
One use case I often have for environment variables is when I want to run some code in production but not in development.
We currently already allow this with process.env.NODE_ENV checks. This is how React determines which code path to use.
Hmm good point. Here's a slightly different example - let's say your app accesses a Firebase backend. There is one that's only used for production, but each developer has their own for local development, so you can stick random experimental stuff in your database without it borking other peoples' environments. One pattern I would use for this is to check an environment variable to get access info for the backend, and have a startup script for development mode that grabbed this from a config file that isn't checked into source control. Is there currently a straightforward way to do this within a create-react-app
-created app?
Maybe I'm missing something here, but what about defining two different scripts in your package.json
?
{
"dev": "SOME_ENV_VAR='development' npm start",
"prod": "SOME_ENV_VAR='production' npm start"
}
and then I think in your app you could have a constants.js
file that exports some commons env vars like that URL:
if (process.env.SOME_ENV_VAR === 'development') {
// export different stuff here
} else {
}
Not 100% sure how a .env
file would make that easier?
The problem I encountered is that IP and PORT are hard coded on the start script, which isn't exactly in the app code.
So just defining some environment variables before running the server is not enough.
Maybe I'm missing something here, but what about defining two different scripts
This currently won’t work because we don’t pass all ENV variables to DefinePlugin
. We only pass NODE_ENV
. We could, however, pass all variables! (This doesn’t seem super problematic to me, and maybe it’s even the right thing to do.)
The problem I encountered is that IP and PORT are hard coded on the start script, which isn't exactly in the app code.
We definitely wouldn’t be hardcoding them when we get to solving this problem. I’m just saying I want to approach this holistically and not just add a bunch of variables one by one without any cohesive system.
Let’s figure out a generic enough system that lets us configure create-react-app
for many scenarios: custom port, serving from cloud9, customizing environment, etc.
Sometimes, like with Code-Push, you have additional constellations like this:
App | Code-Push Deployment |
---|---|
DEV | STAGING |
PROD | STAGING |
PROD | PROD |
So you would need another ENV variable like CODEPUSH_ENV
. So yes, @gaearon I agree we should just throw all the env strings into DefinePlugin
. In fact I'd go so far and say that should be the default behaviour of DefinePlugin
;)
Does DefinePlugin dumps all the environment variables in a js object in the generated output or does a find/replace of all of them?
There are a lot of very sensitive information in environment variables from a security perspective, this is a big attack vector and we don't want to dump it all by default.
It does a find and replace. Not only is that important for security, it also ensures that dead-code-elimination works properly after the environment variables are set.
On the other hand, I would probably not want any npm module I install to be able to expose any of my environment variables, that seems like an auditing nightmare. My inclination would be to do NODE_ENV for all modules (including npm) but maybe do custom environment variables only in application code.
We could choose a namespace, like REACT_APP_ENV
.
Maybe this could be solved instead with dynamic imports - if you do something like
let env;
if (process.env.NODE_ENV == "production") {
env = require("production-env.js");
} else {
env = require("development-env.js");
}
then you could get the effect of environment variables without needing changes in the current runtime.
@lacker the problem is that NODE_ENV is effectively reserved for optimisation. You can't use anything other than NODE_ENV.
I once built an app for one client, and ended up deploying a second identical copy of the app for a different client. The only difference between the two deployments was the company names and branding colours. To do this, I just defined environment variables for each of those features. The issue is that those features vary between different clients, not between development and production.
@gaearon I don't like the idea of a prefix. It feels awkward to have to prefix all the variables with something that has nothing to do with my app, and counter-intuitive that some variables pass through and others do not.
Can we use npm config
for specifying variables like port, proxies, etc (need to figure out a list of them), as well as exposing custom options to the app? The nice thing about it is it can be specified right in package.json
, there’s a CLI to change it, and you can have local overrides or use environment variables... It seems.
By the way I’m coming to the conclusion that specifying ports, proxies and stuff is fair game because we’re competing for system resources. We just need to make sure the defaults work well with zero configuration, but some optional config for shared resources like ports is fine.
I'd suggest for port number we should just use process.env.PORT || 3000
, which is pretty much the standard in node.js. It's what platforms like heroku support.
Port would only be relevant for local development, wouldn’t it?
The reason I’d like to avoid envs by default is that you can’t easily write scripts that use them in a cross platform way. So somebody publishes a react-example
that contains PORT=3001 react-scripts start
, and then somebody else tries this on Windows, and it doesn’t work. Now they can’t learn React from this example. A solution to this is to use a package called cross-env
(or to extract a script and set the process.env.PORT
yourself there) but this is not a very common knowledge.
So I would prefer config
in package.json
because it is cross-platform “by default” but you can also specify envs to override it if you really want to.
For those of you who just needed PORT, you can specify it as an environment variable in the next alpha. Please try it out: https://github.com/facebookincubator/create-react-app/pull/190.
This is not related to this issue so keeping it open.
Neo solves this using an env namespace, like @gaearon proposed. I think that would be preferred over setting config in package.json since some items may be environment specific, and others may have needs for access of sensitive data which should not be committed.
Thanks for the insight! Has this been working well for your users?
@gaearon yes, we have a few different projects that utilize custom namespaced environment variables. I'll open a PR and we can evaluate its merits.
I am in favor of passing env to DefinePlugin. In our use case we end up swapping out a bunch of different service urls. Writing code like:
if (process.env.NODE_ENV === 'development') {
// export different stuff here
} else {
}
to do something that environment variables solve seems suboptimal.
@unscene
Support for custom variables has been implemented in #342. It will be released in 0.3.0
.
Support for NODE_ENV
has been in Create React App since the very first version.
Sweet that sounds great.
As for NODE_ENV I saw it were there just didn't think it was the way to go.
Dig the name-spacing solution though.
Took me half an hour to find out this:
To set a different port for create-react-app you have to create ".env" file in project root directory and set the port like this:
PORT=80
@thg303 and posterity, note that to use a port below 1024, you'll need to sudo
your react-scripts start
command.
@thg303 Did it work for you just by adding the .env file with the env variable? I'm having trouble getting that to work.
@eric-khoury I just test it for changing the port number. I have no idea for other env variables.
@eric-khoury Please note that only env that starts with REACT_APP_…
available in your app. Every other envs (such as PORT) only available in build process
@dvkndn Thx for the info, I missed that part completely.
Simple question @all, how can we inspect the value of NODE_ENV in the front-end React code? I assume this is passed to the front-end given this conversation?
Is there a way to set a default NODE_ENV on the server as well? Perhaps by editing the .env file? I assume you have to npm run eject to do that? Or not?
You could always just alias it with the REACTAPP prefix if it's not available
From: Operations Research Engineering Software+ notifications@github.com Sent: Dec 12, 2016 9:53 PM To: facebookincubator/create-react-app Cc: Ryan Fairchild; Mention Subject: Re: [facebookincubator/create-react-app] A way to define custom environment variables (#102)
Simple question @allhttps://github.com/all, how can we inspect the value of NODE_ENV in the front-end React code? I assume this is passed to the front-end given this conversation?
- You are receiving this because you were mentioned. Reply to this email directly, view it on GitHubhttps://github.com/facebookincubator/create-react-app/issues/102#issuecomment-266621353, or mute the threadhttps://github.com/notifications/unsubscribe-auth/AADdT4RzoEf5ogcwNpKbKnzb05z034rtks5rHgi0gaJpZM4JTJJ0. This e-mail message, and any attachments, is intended only for the use of the individual or entity identified in the alias address of this message and may contain information that is confidential, privileged and subject to legal restrictions and penalties regarding its unauthorized disclosure and use. Any unauthorized review, copying, disclosure, use or distribution is strictly prohibited. If you have received this e-mail message in error, please notify the sender immediately by reply e-mail and delete this message, and any attachments, from your system. Thank you.
@ORESoftware could you use console.log(process.env.NODE_ENV)
?
@ORESoftware you have to set NODE_ENV via os environment variable. in linux it would be like executing this command in the terminal:
NODE_ENV=production && npm run build
@thg303 thanks, I got that part :) what I am not sure of, is if this value is sent by create-react-app or if I have to do that manually. or any other env values besides NODE_ENV
If it is sent to the front-end, how can I access the value for NODE_ENV on the front-end sent from the backend?
Basically looking to render things differently depending if I am dev or prod, etc.
Simple question @all, how can we inspect the value of NODE_ENV in the front-end React code? I assume this is passed to the front-end given this conversation?
Have you had a chance to read the corresponding section in the User Guide? It specifically answers this question with an example. TLDR: it’s process.env.NODE_ENV
. It is replaced at the build time so you get "development"
on npm start
but a production bundle created with npm run build
will hardcode this to "production"
.
If it is sent to the front-end, how can I access the value for NODE_ENV on the front-end sent from the backend?
You can't "send" it from backend. If it's on the backend, your app is already compiled in production mode, so it's "production"
.
you have to set NODE_ENV via os environment variable. in linux it would be like executing this command in the terminal:
This answer is incorrect. With Create React App NODE_ENV
is hardcoded depending on whether you used npm start
or npm run build
. You can't override it (precisely because people sometimes override it wrongly and end up with bloated builds since they get a slow development version of React). However you can specify REACT_APP*
variables, as described in User Guide I linked to above in this comment.
@gaearon so basically in short, you can do:
REACT_APP_NODE_ENV=development
and on the front end, we have:
const nodeEnv = window.REACT_APP_NODE_ENV` // (likely incorrect)
but looking at the link, you sent, it looks like:
render() {
return (
<div>
<small>You are running this application in <b>{process.env.NODE_ENV}</b> mode.</small>
<form>
<input type="hidden" defaultValue={process.env.REACT_APP_SECRET_CODE} />
</form>
</div>
);
}
that would mean that instead of
const nodeEnv = window.REACT_APP_NODE_ENV` // front-end
instead on the front-end we have
const nodeEnv = process.env.NODE_ENV` //front-end
It's a little counterintuitive to have Node.js related stuff on the front-end, but I guess that's pretty normal now that we are using Webpack etc. We have to use surrogates for some of the backend code (like process, fs, etc).
thanks
@ORESoftware
No, NODE_ENV
is the built in one. It's the only variable that is available by default and it doesn't need REACT_APP
prefix. You read it like this:
var env = process.env.NODE_ENV;
As I already mentioned, User Guide contains an example that specifically shows this. I recommend giving it another look.
For any custom variables, you'd use REACT_APP
prefix. But NODE_ENV
is built-in, doesn't have a prefix, and you can't specify it yourself—its value depends on whether you're in development or a production mode.
Please refer to the section in User Guide, I'm just repeating what it says here.
@gaearon ok I just read what you wrote, np. However the user guide does not seem to demonstrate how to access the variables in the front-end, at least not in the same section (tell me if I am wrong :)
I have this
"start-dev": "REACT_APP_NODE_ENV=development && react-scripts start",
on the front-end
if I log process.env, I get an empty object. So I am guessing that instead of doing
process.env.REACT_APP_NODE_ENV
it will be
window.REACT_APP_NODE_ENV
I will test it out, but if it's it not in the docs yet, I would be happy to add whatever the right way to do this is.
e.g. window.R = no search results
This may be a tiny yet non-obtrusive solution. Allow a custom
.env.js
file that exports a key value pair used for custom webpack defines. I guess this wont be useful for many, since you any way get to refer to NODE_ENV but I also used this for defining a publicPath from an environment variable or defaulting to root. (useful for me as i had to run the same app for multiple quizzes, so I could build the frontend without configuring anything and having sane default not-get-in-the-way configs while development and testing)