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
.