Simplifying Development with Monorepos

In the world of software development, managing multiple projects can be a daunting task. To simplify this process, many developers turn to monorepos – a single repository that contains all the code for a project or organization.

Benefits of Monorepos

Monorepos offer several benefits, including:

  • Improved visibility: With all code in one place, it’s easier to see how different components interact and depend on each other.
  • Simplified dependency management: Sharing dependencies between projects becomes much easier when they’re all in the same repository.
  • Streamlined development: Monorepos enable developers to work on multiple projects simultaneously without having to switch between different repositories.

Building a Decoupled Monorepo Project

When building a decoupled monorepo project, it’s essential to have separate package.json files for each system. This allows for easy movement and integration of individual systems into other projects if needed.

While it’s possible to have a single package.json file as the source of truth for the package, this approach can become cluttered and unscalable quickly.

To manage dependencies effectively, consider using tools like Lerna, which enables common dependencies to be stored under the root directory and specific dependencies to be stored under specific folders for each project.

Deploying a Monorepo to Heroku

In this example, we’ll deploy a basic monorepo to Heroku, consisting of a client and server application built with TypeScript.

We’ll use a single package.json file in the root directory to control the build processes of both applications.

Setting Up the Client App

First, create a new folder and run npm init -y to generate a package.json file.

Next, create two separate folders for the client and server applications.

For the client application, we’ll use Vite, a build tool that supports React, Vue, and Svelte.

Run the following command to create a new frontend application with Vite:


npm create vite@latest client -- --template react-ts

This will prompt you to choose a framework; select React and then react-ts as the variant.

Now, navigate to the client folder and run npm install to install all dependencies.

Configuring Proxy Settings

Update the vite.config.ts file to include the following proxy settings:

“`javascript
import { defineConfig } from ‘vite’
import react from ‘@vitejs/plugin-react’

export default defineConfig({
plugins: [react()],
server: {
proxy: {
‘/api’: ‘http://localhost:8080’,
},
},
})
“`

This will allow us to make requests to the server application during development.

Setting Up the Server App

Create a new folder for the server application and run npm init -y to generate a package.json file.

Since we’re using React with TypeScript, it’s good practice to use TypeScript for the server application as well.

Run the following command to generate a configuration file for TypeScript:


npx tsc --init

Update the tsconfig.json file to include the following settings:

json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"rootDir": "./src",
"outDir": "./dist",
"esModuleInterop": true,
"strict": true
}
}

This will configure TypeScript to compile our server code and output it to the dist folder.

Installing Dependencies

Install the required dependencies for the server application, including typescript, @types/node, @types/express, and ts-node-dev.

bash
npm install --save typescript @types/node @types/express express ts-node-dev

Creating a Simple Server

Create a new file called index.ts in the src folder and add the following code:

“`typescript
import express from ‘express’

const app = express()

app.use(express.static(‘client/dist’))

app.get(‘/api/test’, (req, res) => {
res.send({ message: ‘Hello from server!’ })
})

const port = 8080

app.listen(port, () => {
console.log(Server started on port ${port})
})
“`

This will create a simple server that serves static files from the client/dist folder and responds to GET requests to the /api/test endpoint.

Testing the Server

Start the server by running npm run dev in the server folder.

Open a new terminal window and navigate to the client folder.

Run npm run dev to start the client application.

Open a web browser and navigate to http://localhost:3000.

You should see a page with a button that says “Click me!”

Click the button to send a request to the server.

You should see a response from the server in the browser console.

Deploying to Heroku

To deploy our application to Heroku, we need to create a package.json file in the root directory of our project.

Add the following scripts to the package.json file:

json
"scripts": {
"build": "npm run build --prefix client && npm run build --prefix server",
"start": "npm run start --prefix server"
}

This will tell Heroku to build our client and server applications and then start the server.

Create a new file called Procfile in the root directory of our project.

Add the following line to the Procfile:


web: npm run start

This will tell Heroku to start our server when our application is deployed.

Commit our changes and push them to Heroku.

Our application should now be deployed to Heroku and accessible at https://<app-name>.herokuapp.com.

Leave a Reply

Your email address will not be published. Required fields are marked *