Building a CI/CD Pipeline for a Node.js + React Monorepo
Discover how to set up a CI/CD pipeline for your Node.js and React monorepo using GitHub Actions, ensuring efficient builds, tests, and deployment.
Building a CI/CD Pipeline for a Node.js + React Monorepo
In modern web development, having a CI/CD (Continuous Integration/Continuous Deployment) pipeline is crucial for streamlining the process of delivering applications. In this article, we'll walk through setting up a CI/CD pipeline specifically for a Node.js backend and a React frontend that share a monorepo structure. We'll use GitHub Actions as our CI/CD tool, leveraging its capabilities to automate testing and deployment.
Prerequisites
Before we jump in, you should have the following:
- A basic understanding of Node.js and React.
- A GitHub account with a repository set up for the monorepo.
- Familiarity with YAML syntax for configuring GitHub Actions.
Monorepo Structure
First, let's outline our monorepo structure. Here’s a simple example:
/my-monorepo
/packages
/backend (Node.js app)
/frontend (React app)
package.json
yarn.lock
We will be using Yarn Workspaces to manage our dependencies efficiently.
Setting Up Yarn Workspaces
In your root package.json, you should define the workspaces:
{
"name": "my-monorepo",
"private": true,
"workspaces": [
"packages/*"
],
"scripts": {
"build": "yarn workspaces run build",
"test": "yarn workspaces run test"
}
}
Make sure to initialize both your frontend and backend directories with their own package.json files that define appropriate scripts for build and test.
Configuring GitHub Actions
Now that we have our monorepo structure and package management in place, it's time to set up GitHub Actions.
Creating the Workflow File
In your GitHub repository, create a directory called .github/workflows and add a new file named ci-cd.yml.
Here’s a sample workflow:
name: CI/CD Pipeline
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Install dependencies
run: |
yarn install
- name: Run backend tests
working-directory: ./packages/backend
run: |
yarn test
- name: Run frontend tests
working-directory: ./packages/frontend
run: |
yarn test
- name: Build applications
run: |
yarn build
- name: Deploy to production
if: github.ref == 'refs/heads/main'
run: |
# Add your deployment script here
echo "Deploying to production..."
Explanation of the Workflow
- Triggers: The pipeline triggers on a push or pull request to the
mainbranch. - Jobs: We define a single job called
buildthat runs on the latest Ubuntu image. - Checkout code: Retrieves the code from the repository.
- Set up Node.js: Configures the Node.js version required for the application.
- Install dependencies: Uses Yarn to install all dependencies for the projects.
- Run tests: Executes tests for both the backend and frontend. Customize these commands based on your test frameworks (like Jest, Mocha, etc.).
- Build applications: Builds both applications in preparation for deployment.
- Deploy to production: The deployment step is conditional, only running on changes to the
mainbranch.
Deployment Strategy
For the deployment step, you might want to deploy to platforms such as Heroku, AWS, or Vercel. Here’s an example for deploying to Vercel:
- First, add your Vercel token to the repository secrets in GitHub (Settings -> Secrets and variables). Name it
VERCEL_TOKEN. - Update the deployment step in your workflow file:
- name: Deploy to Vercel
if: github.ref == 'refs/heads/main'
run: |
npx vercel --token ${{ secrets.VERCEL_TOKEN }} --prod
This command deploys your app directly to Vercel utilizing the Vercel CLI.
Improving Your CI/CD Pipeline
Caching Dependencies
To speed up the workflow, you can cache your dependencies. Here’s how you can do that in the ci-cd.yml file:
- name: Cache Node.js modules
uses: actions/cache@v2
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
This caching will reduce the time needed for dependency installation by storing the node_modules.
Notifications
Consider adding notifications to your workflow to keep your team updated on the status of the CI/CD process:
- name: Notify on Failure
if: failure()
uses: peter-evans/slack-send@v1
with:
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
message: 'CI failed on ${{ github.ref }} at ${{ github.event.head_commit.timestamp }}! Check the logs.'
Conclusion
Setting up a CI/CD pipeline for a Node.js and React monorepo using GitHub Actions streamlines the development workflow, allowing for efficient code integration and deployment. By leveraging the power of GitHub Actions, Yarn Workspaces, and optimizing steps like caching and notifications, we ensure that our applications remain reliable and up-to-date.
Feel free to customize the scripts further to fit your team's needs and explore more features of GitHub Actions for additional improvements. Happy coding!