Categories
Node.js

What is a good directory structure for a monorepo with a Node.js back end and React front end?

3 min read

Do you want to keep your Node.js back end and React front end in the same git repository, but aren’t really sure how to structure it? Perhaps you’ve heard about monorepos as a solution to this, but you aren’t really sure where to start. It’s often decisions like these which feel like they should be simple, but quickly turn into a confusing problem!

Setting up your project repository as a monorepo typically requires learning how to use a tool like Yarn or Lerna, as well as managing multiple package.json files with different dependencies. It’s also going to require a bunch more configuration if you want to use a continuous integration service with your monorepo, and you’ll also need to think about even more configuration to get everything deployed. The good news is that for most projects you probably don’t need to set them up as a monorepo, as there’s a much simpler way to organise your front end and back end code in the same repository, while still keeping the code cleanly separated.

Let’s dive straight in with an example directory and file structure for a project with a Node.js back end and a React front end. It might look like this:

├── src
│   │
│   ├── client  <- Front end code
│   │   ├── components
│   │   │   └── ExampleComponent.js
│   │   └── index.js  <- The main entrypoint for your front end React application
│   │
│   └── server  <- Back end code
│       └── app.js  <- The main entrypoint for your Node.js back end server
│
├── package.json  <- Specifies front end and back end dependencies
├── package-lock.json
├── README.md
└── webpack.config.js  <- Configuration for compiling front end assets

In most cases it is simpler to have a single package.json in the root of your repository which defines the dependencies for both your front end and back end. The front end and back end code is neatly organised into separate directories, and the standard npm install command will be able to install the dependencies for both. This is a lot simpler than having to learn, add and configure a tool to your project just to perform basic development tasks. It will also be compatible with pretty much any continuous integration or deployment service that you might choose to use.

Here is an example package.json which specifies all the dependencies which the front end and back end require, as well as some npm scripts that help with building the front end assets and running the Node.js back end server:

{
  "name": "example-app",
  "scripts": {
    "build": "webpack --mode development --entry ./src/client/index.js --output ./static/bundle.js",
    "start": "node src/server/app.js"
  },
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "@sucrase/webpack-loader": "^2.0.0",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "sucrase": "^3.15.0",
    "webpack": "^4.43.0",
    "webpack-cli": "^3.3.12"
  }
}

You might have noticed that the dependencies for the React front end are specified under devDependencies. This is because after the front end assets (normally CSS and JavaScript) have been built they are not needed for deployment, and most sensible deployment systems will remove any installed devDependencies to reduce the size of what they’re deploying.

The dependencies for the Node.js back end are specified under dependencies as they need to be deployed for the Node.js server to be able to run.

To help you understand how this structure can work for your React and Node.js project I’ve created an example project on GitHub which you can clone and explore.

The nice thing about this approach is that you’re not locked in to any extra tooling. If you do find that your project becomes more complex in future, and you decide that you do need to organise it as a monorepo, there’s nothing about this simplified structure which will get in the way of you changing things around.

Update October 2020: If you’re still keen to structure your project repository as a monorepo, npm v7 (which is installed with Node 15) now supports "workspaces" in a very similar way to Yarn. This is a really nice feature addition as it means one less tool to learn if you want to set up your project as a monorepo. Read more about npm workspaces.

4 replies on “What is a good directory structure for a monorepo with a Node.js back end and React front end?”

What would be the best way to go about deploying this kind of project structure? Would it be easier to deploy them separately (ex – deploy client folder to netlify, server folder to heroku), or is there an easier way?

It really depends on your project and its specific requirements, however in general I’d try and keep things with one hosting provider so that there are less services for you to manage.

If you take a look at the example project I created for this post you’ll see that I’ve configured the Express back end to serve the static assets (e.g. CSS and JavaScript) which are compiled by webpack from the source files in the client directory: https://github.com/simonplend/example-app-nodejs-backend-react-frontend#application-structure. This means that the front end, as well as any potential back end API endpoints, are all served by the same Node.js application. You would then only need to deploy to a single hosting provider like Heroku.

If your site is getting a lot of traffic a next step would be to consider configuring a CDN (Content Delivery Network) like Cloudflare or Fastly to serve your static assets.

Comments are closed.