How to get .env from root project into React client - node.js

I'm trying to do something that should be REALLY simple but it's proving exceedingly difficult. I've burned 4 hrs on this today. I have a nodeJS project with server and client parts. I'm using concurrently to launch them both. I want to use the same .env for both server and client. Should be simple, right? Apparently not. The problem is that when I try to use dotenv in my React client, it never finds the .env no matter what I do, and the reason is that __dirname (and process.cwd()) always point to the root directory (i.e. /). I need it to be a relative path, or at least I need to pass somehow the explicit path to my react app.
I've even tried running the client directly by calling 'npm start' from my client directory - the process.cws() still defaults to the root partition and not my project directory.
My directory structure is as follows:
+project_root
- .env
- index.js
- package.json (for the server side)
+ client
- package.json (for client)
+ src
- App.js (this is where I'm trying to access .env)
My package.json for the server has the following in the scripts section:
"scripts": {
"start": "node index.js",
"start-watch": "nodemon index.js",
"dev": "concurrently \"npm run start-watch\" \"cd client && npm start\""
}
On the client side I have
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
I normally start all of this from the project root by calling 'npm run dev'. However, I thought to try and build a run script for it, and from my run script pass in environment variables of the form REACT_APP_
The above works, but in the absence of being able to actually get REACT to set itself to be in a directory other than root, I still cannot get React to read the project .env.
What I've been trying next is to have my run script output all the contents of .env as REACT environment variables. I so far haven't got it to work, here is the run script I tried:
!/bin/sh
export REACT_APP_CURR_DIR=`pwd`
grep -v '^#' .env | while read line
do
echo exporting line $line
VARNAME=REACT_APP_`echo $line | sed -E 's/(.*)=.*/\1/'`
VALUE=`echo $line | sed -E 's/(.*)=(.*)/\2/'`
echo $VARNAME
`export ${VARNAME}=${VALUE}`
done
npm run dev
When I do this, it barfs on some of the variables, but none of them make it into process.env within my react client.
Am I missing something very basic here? I feel like I've gone to extreme lengths just to have server and client use the same .env file so I'm not duplicating parameters everywhere. Even if I put a .env file in my client, the fact that even executing npm start is not giving the React app the right directory is problematic.
I can't believe no one has come into this before.

Related

Connecting server in root package.json

I have a React app and here is my folder setup:
If I cd src and then run node server.js, I can see my server is running based off messages in added into console.log.
But when I'm in the root folder and I run npm start, the server.js is not connected. Here is my root package.json, what am I missing?
If you want to run react app and server simultaneously, you can use concurrently. Install it, and modify your scripts section so you will have separate entries for react-scripts start and node src/server.js. Then you can run them both with concurrently. It will look something like this:
{
"scripts": {
"start-react-app": "react-scripts start",
"start-server": "node src/server.js",
"start": "concurrently \"npm:start-react-app\" \"npm:start-server\""
}
}
This way, when you run npm start it will launch both scripts.

npm run points to different .env file

We are working on nodeJs/ExpressJs we have configured multiple .env files for development and production and pointing it to package.json for different execution process, we have naming conversation issues at scripts.
Whenever we run npm run prod it takes to preprod configuration. what could be the issues?
Update: we have figured that the suffix of the script key is the same in the next script, after update/rename preprod to preProd the both runs fine. but why?
Eg :
"scripts": {
"dev": "clear; env-cmd -f ./config/hostedDev.env nodemon --exec babel-node index.js",
"prod": "clear; env-cmd -f ./config/prod.env nodemon --exec babel-node index.js",
"preprod": "clear; env-cmd -f ./config/preprod.env nodemon --exec babel-node index.js"
},
Apparently the issue is with the word 'pre'.
If you would have noticed it runs both preprod and prod commands (pre running first).
If you change the script name to 'postprod' the postprod script will run later.
So, I guess npm uses 'pre' as to run before the 'prod' script and then running 'prod' script itself.

Is it possible to run nodemon to restart server upon changes on front-end?

I'm rather new to this area, so please excuse if this question is completely basic. I've seen some tutorials use nodemon to watch files, and restart servers on Nodejs backend. I've seen others use webpack to watch files such as create react app on frontend. Can you actually use nodemon to watch files and refresh pages on the front end?
Yes I believe you can set it up with your package.json scripts!
For instance with a node server with a create-react-app within a client folder you could declare a start script along the lines of:
"start": "concurrently \"nodemon server.js\" \"cd client && nodemon start\""
Then when you run npm start this will run nodemon on both the server file and the client folder
Just be aware this assumes your server file is named server.js and your client files are in a folder named client and will require you to have the concurrently dependency installed.
You could use something like this one if you already have create react app within a client folder.
"server": "nodemon server.js",
"client": "cd client && yarn start",
"dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\""
Concurrently allows us to run both on one terminal as well as it allows us to pass --kill-others-on-fail which means that if one breaks (control + c on mac), the other one will also break

multiple package.json files in react nodejs project

I am new to react and am trying to create a project that makes use of react, node, and express. Having a lot of issues setting up react correctly by myself, I decided to use create-react-app.
I found a bunch of tutorials online and a lot of them seem to suggest separating the front end and the back end into different directories resulting in two package.jsons.
so the project structure would look something like this:
Root
|
------client
| |
| -------package.json with front end dependencies
|
package.json with the back end dependencies
The client diretory is the one created with "npm init react-app" and also contains the package.json that has the react-scripts. Currently if I use command "npm run build" in the client directory it creates a build without the backend files inside the root folder, and if I use "npm run build" in the root folder it doesn't work because I do not have create-react-app scripts in that package.json.
My main question is how would I make a build of my project if I have two package.jsons and if it is normal/best practice to split up front end and back end like this?
Any advice would be much appreciated.
This folder structure is one of the most used structure. You are actually separating front-end and back-end, that would result in scalable architecture.
To build your project from one single command, you need to install a dependency concurrently. It will enable multiple commands at once. Then make changes to your root package.json.
Below is an example package.json :
"scripts" : {
"build-client": "npm run build --prefix <FRONTEND_FOLDER NAME>",
"build": "<YOUR SERVER BUILD COMMAND>",
"build-project" : "concurrently \"npm run build\" \"npm run build-client\""
}
Hope it helps!!!
I think you have to separate CRA(create-react-app) and backend server(express).
This means you have to run front and back in different port and then make a npm scripts that boths run front and back.
Like this.
ROOT/package.json
"client": "cd client && yarn start",
"server": "nodemon server.js",
"dev": "concurrently --kill-others-on-fail \"yarn server\" \"yarn client\""

I am missing something about .env, could you explain it to me?

I have a very, basic, need: to store different endpoints for my APIs according to the environment. Suppose a simple file like this:
API_URL=http://localhost:8080
it should become, for my prod environment:
API_URL=http://myprodServer
and I'd like to have an integration test and a uat endpoint too!
Looking at my package.json I see:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
So my idea is:
Put a command line argument near to "build" and "start" so to specify local and production enviroment files
Have a way to access to said configuration in my app, say config.API_URL
Now, I come from spring boot, and in spring boot I have a file per environment.
I though dotenv could be my solution but I see two strange things on their website:
Please don't commit your .env file --> so, how are my colleagues supposed to build my application? I usually at least push local and test environment, while keeping the uat and production files directly under the server
You should have just one .env file --> ok this one destroys me: if I just have one file how am I supposed to handle several environments???
What am I missing here? Could you help me solve my problem? I'm new to npm so I'm a little confused...
It looks like you are using CRA to develop your React app. If so, your env variables should be REACT_APP_API_URL=http://localhost:8080. Notice the prefix. If you are using CRA, you must use the prefix. More about that here. If you do this correctly, the variable should be available in your javascript by using process.env.REACT_APP_API_URL.
At work, we each have a copy of the .env files locally, since we don't check it in. We have different .env files for each environment - e.g - .env.production, .env.development, .env.stage. We then have a run and build script for each environment in our package.json. Using env-cmd package, our scripts might look like this:
{
...
...
"start": "react-scripts start",
"start:stage": "env-cmd .env.stage.local react-scripts start",
"start:production": "env-cmd .env.production.local react-scripts start",
"build": "react-scripts build",
"build:stage": "env-cmd .env.stage.local react-scripts build",
"build:development": "env-cmd .env.development.local react-scripts build",
...
...
}
Along with this, we also have a git branch per environment so that on stage branch we would run npm run build:stage and deploy to Stage environment. We would do the same for production.
After looking around for a multi-environment setup, this is what I settled on and it works ok. However, I'd be open to improving the process.

Resources