How to organise file structure of backend and frontend in MERN - node.js

I have backend based on express + mongoose. File structure is:
- /models
-- item.js
- /node.modules
-- ...
- server.js
- package-lock.json
- package.json
And regular create-react-app based folder for front-end:
- /src
-- /assets
--- index.css
-- /components
--- Somecomponent.js
-- /containers
--- App.js
-- /reducers
--- somereducers.js
- /node.modules
-- ...
-- index.js
-- registerServiceWorker.js
- .gitignore
- package-lock.json
- package.json
I want to use it in proper way together. I wanted to organise it this way:
- /client
-- /src
...
-- index.js
-- registerServiceWorker.js
- .gitignore
- package-lock.json
- package.json
- /server
- /models
-- item.js
- /node.modules
-- ...
- server.js
- package-lock.json
- package.json
At this stage I stuck. I can make it if client folder inside server folder or if server folder inside client.
1. But how to make it run when two folders are siblings?
2. What should be package.json and where node.modules should be (whether both server and client should have it's own package.json and modules?)

The most basic structure would be to have a root folder that contains frontend and backend folders. Since you're talking about the MERN stack, you would have a package.json inside of your NodeJS backend environment and a package.json for your React side of things. Backend server and the frontend client are two totally separate things, so yes, they both have their own node_modules folders. On the backend, you'll probably have installed something like Express for your Node runtime, Mongoose for a more convenient way to talk to your MongoDB, etc, and on your frontend, you'll have your React as your frontend framework, Redux for state management, etc. Additionally, depending on what you have already listed inside of your package.json files, when you run npm install separately it will be installed in those two folders. If you want to install additional packages, just run npm install + "the name of the package" (without the '+' and without the quotes) inside of that particular folder where you need it (backend or/ and frontend).
I hope this was helpful. Check out the pics, especially the 2nd one.
App structure
Folder structure
UPDATE:
In development, I suggest installing two additional things:
npm i -D nodemon
npm i -D concurrently
Note: The -D flag will install them as devDependencies.
nodemon is going to track every file change and restart the backend server for you. So, it's obvious that it should be installed inside of the "backend" folder. All you have to do is go inside of the package.json file (backend) and add a new script. Something like this:
"scripts": {
"start": "node app.js", // in production
"dev": "nodemon app.js", // in development
}
concurrently allows you to start both your frontend and backend at the same time. I suggest initializing a new Node project inside of the top-level root folder -[folder which contains both, your frontend and backend]. You would do that with the npm init command, and after that, install the concurrently package there.
Now, go open your newly created package.json file inside of your root folder and edit the start section, like this:
"scripts": {
"dev": "concurrently \"cd backend && npm run dev\" \"cd frontend && npm start\" "
}
What this will do is go inside of the backend folder and run the dev command (the same one we just configured), so that will start nodemon. Additionally, it will also go inside of the frontend folder and run the default start command -which is exactly what we want.
If you kept the folder structure, installed all the dependencies (including the additional two I mentioned above), changed the package.json file inside of your root folder, you'll be able to start them both with a simple command:
npm run dev // make sure you're inside of the root folder when doing so :)

Adding to the accepted answer, the folder structure division inside the frontend and backend is more useful if it is based on business logic rather than tech logic.
Dividing the whole stack into self-contained components that preferably don't share files among them is the best way to make your app more testable and easy to update. This in the smallest possible way is what commonly known as microservice architecture.
Bad Design : difficult to update and test:
Good Design : easy to update and test:

Use Structure as per your requirement, like based on the project scope or depth. But make sure to keep the endpoints and models separate, so initially have a setup like such
src/
controllers - for the endpoints
models - for the schema
server.js - or index.js

Related

How to setup and run ionic app and node express api within one application?

I have two separate applications one is the ionic app and other is node express api app. Is it possible to merge both in one application? Like for example when i enter npm run start it should run ionic serve and node index js both?
Typically after you finish developing your frontend you "build" it. This minifies and optimizes frontend files. For ionic: https://ionicframework.com/docs/cli/commands/build
This creates a folder(the default name can be "dist" or "build" etc). You put this folder in your backend folder, then serve it statically. For static serving check out https://expressjs.com/en/starter/static-files.html.
This way you deploy only backend, and it works. You can make api endpoint routes start with "/api" and "/" routes can be for frontend's static serving.
If you mean you want to do that for development purposes only, you can use concurrently command https://www.npmjs.com/package/concurrently
npm install -g concurrently
After installation, add this line to package.json script
"start": "concurrently \"command1 arg\" \"command2 arg\""
In command1: add ionic start command, like: ionic start
In command2: add node start command, like: nodemon server.js

How to deploy NodeJS multi module/package project? (frontend & backend)

I tried to create a multi module/package project with npm today.
The structure is as following:
root
|
|____ backend <-- npm package containing all routes
|
|____ frontend <-- npm package containing all js/html/css files
|
|____ dist <-- merged output from backend & frontend
|
|____ build_and_run.sh <-- shell script to invoke npm in both - frontend and backend and run the final application in "dist/"
The frontend should be in the "dist/static" directory.
Both - the frontend and backend are using different dependencies and compiling steps (TypeScript, VueJS etc.), so the differentiation between frontend and backend currently makes the most sense to me.
My problem is the deploying of both modules/packages into the final directory.
Copying the files isn't a problem, but deploying dependencies into the "dist" directory is (e.g. express).
The second goal is to create a Docker file, but this option shouldn't be neccessary for running the server.
If someone has a better structure or solution fitting my needs, I would definitely appreciate to hear it.

Deploy the backend and frontend on the same Heroku app/dyno

At the root of my project, I have a frontend and backend folder. Both folders contain a package.json that list their dependencies. How do I tell Heroku to run npm install on both folders when deploying the application? It seems like Heroku expects to have a single package.json file by default. Do I have to do something with a Procfile? The Heroku documentation doesn't seem to tell much about my specific question.
Thanks for the help!
I just successfully completed this goal using static files created during a heroku postbuild step, as described in this blogpost. I have a React frontend (could be anything though) and Express API backend. Each process has its own port in dev, but deploying on Heroku uses just one total.
Put the working frontend in a subdirectory of root (such as /frontend).
Put the working backend in a subdirectory of root (such as /api -- the blogpost assumes the backend remains in the root directory -- either way is fine).
Proxy API requests from the frontend to the backend by adding this line to /frontend/package.json (replacing 5000 with your backend port):
"proxy": "http://localhost:5000",
Add the following to api/app.js (or api/index.js) in the backend (be sure the last part is AFTER you define the appropriate backend [or api] paths):
const path = require('path')
// Serve static files from the React frontend app
app.use(express.static(path.join(__dirname, '../frontend/build')))
// AFTER defining routes: Anything that doesn't match what's above, send back index.html; (the beginning slash ('/') in the string is important!)
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname + '/../frontend/build/index.html'))
})
Edit the root directory's /package.json file with something like the following (note that using the concurrently package allows an easy way to run the whole app locally with npm run dev, but only heroku-postbuild is required here):
"scripts": {
"frontend": "cd frontend && npm start",
"api": "cd api && nodemon app.js",
"dev": "concurrently --kill-others-on-fail \"npm run api\" \"npm run frontend\"",
"heroku-postbuild": "cd frontend && npm install && npm run build"
},
Make sure you install all backend package dependencies in the root directory, or you will get errors.
Make sure your /Procfile has something like web: node api/app.js
Seems that you can put a package.json file on the root of the project and use scripts to invoke npm i in both folder.
https://devcenter.heroku.com/articles/nodejs-support#customizing-the-build-process
Something like cd front && npm i && cd ../back && npm i
But i should say that if they are running on different ports, it may not work as it seems that only one web process per procfile is available.
this last point is to confirm.
You can define several entry points for your project in the Procfile :
web: cd front && npm i && npm start
server: cd backend && npm i && npm start
However, you have to upgrade to Hobby at least. It's 7$/dyno/month.

Deploying hapi.js app in heroku

I'm currently trying to deploy a hapi.js app to heroku with this file structure:
.git
client
server
The hapi.js server is inside the server folder along with it's package.json file, node_modules and all that stuff.
Inside the client folder, I have all the front-end related things (small angular app with bower_components and a gulp script to inject everything). The server.js from /server is serving both the bower_components and the angular app related files.
My current problem is that, obviously, Heroku doesn't find a way to deploy my app because of its structure, since it needs to have the server and package.json on the root of the project (which i'm trying to avoid at all costs).
So far I tried to put on my Procfile the following:
web: node server/server.js
but unfortunately it didn't let me push because it didn't match any of its buildpacks.
Have you add .bowerrc file
.bowerrc file contains
{
"directory": "client/bower_components"
}
and add bower.json in root.

How to serve the default angular seed/tutorial app on the root route?

I'm using the angular tutorial as base to build an app . However when I run npm start I need to go to localhost:8000/app/ to get the app. I would like to change the route so that I can run serve the app on the root path ( localhost:8000/app/) . Where can I configure that ? I've tried to simply move the content from /app into the root but it breaks the npm/build script.
Without running the project myself (it's Sunday after all), it looks like you would need to add the /app path to the start command inside package.json. Also check http-server docs for more on the defaults -
https://www.npmjs.org/package/http-server
Other things may be relying on the root being ./, so there may be some breakage.
Should read something like
"start": "http-server /app --domain 0.0.0.0 --port 8000",

Resources