Managing Multiple Gatsby Projects in a Monorepo - A Unified Build Strategy
In modern web development, projects often share components, styles, or even parts of a website between each other. So, maintaining these projects efficiently, especially when they are supposed to work with each other, could be rather cumbersome. That’s where the monorepo shines.
In this article, we’re going to discuss how to set up a monorepo with two Gatsby projects and one shared component library. We’re going to go over one unique way of deploying where we copy the build files from one project into another, allowing them to run under one single localhost port.
Why Use a Monorepo?
Monorepo allows multiple projects to coexist in a single repository, offering easy sharing of code, uniformity in tooling, and management of dependencies. That would be great in situations where you have related projects, which would share common components or that needed to be deployed together.
Setting Up the Monorepo
-
Initial Setup
First, let’s create a monorepo structure using npm. If you haven’t already, set up npm workspaces in your project.
mkdir my-monorepo cd my-monorepo npm init -y
Now, configure npm workspaces in your
package.json
{ "name": "my-monorepo", "version": "1.0.0", "private": true, "scripts": { "build": "npm run build:project-one && npm run build:project-two", "build:project-one": "npm run --workspace=packages/project-one build", "build:project-two": "npm run --workspace=packages/project-two build", "build:shared-components": "npm run --workspace=packages/shared-components build", "develop": "npm run develop:project-one && npm run develop:project-two", "develop:project-one": "npm run --workspace=packages/project-one develop", "develop:project-two": "npm run --workspace=packages/project-two develop", "clean": "npm run clean:project-one && npm run clean:project-two", "clean:project-one": "npm run --workspace=packages/project-one clean", "clean:project-two": "npm run --workspace=packages/project-two clean", "clean:shared-components": "npm run --workspace=packages/shared-components clean" }, "keywords": [], "workspaces": [ "packages/project-one", "packages/project-two", ] }
-
Creating the Projects
Next, we’ll create our two Gatsby projects and a shared component library inside the packages directory
mkdir packages cd packages npx gatsby new project-one npx gatsby new project-two mkdir shared-components cd shared-components npm init -y
-
Setting Up the Shared Component Library
Next, we’ll create a shared-components package to store reusable components that can be used across multiple Gatsby projects.
-
Creating an
index.js
File in shared-componentsIn the shared-components package, create an
index.js
file that exports all the components// packages/shared-components/src/index.js export { default as Button } from './Button'; export { default as Header } from './Header'; // Add other components as needed
This allows you to import all components from the shared-components package using a single import statement in your other projects.
-
Creating an
Button.js
File (Simple React component) in shared-componentsIn the shared-components package, create a simple React component
mkdir src fsutil file createnew Button.js 0
Add the following code to
Button.js
import React from 'react'; const Button = ({ children, onClick }) => { return ( <button onClick={onClick} style={{ padding: '10px', backgroundColor: '#007bff', color: '#fff', border: 'none', borderRadius: '5px' }}>{children}</button> ); }; export default Button;
-
Creating an
-
Integrating the Shared Components into Gatsby Projects
To use the shared components in our Gatsby projects, we’ll need to install the shared-components package in both projects
cd ../project-one npm install ../shared-components cd ../project-two npm install ../shared-components
Or, You can manully add the shared-components package as to the both projects as follows
Gatsby project-one’s
package.json
{ "name": "project-one", "version": "1.0.0", "private": true, "description": "Gatsby project-one", "author": "", "scripts": { "develop": "gatsby develop", "start": "gatsby develop", "build": "gatsby build", "serve": "gatsby serve", "clean": "gatsby clean" }, "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.15.11", "@mui/lab": "^5.0.0-alpha.166", "@mui/material": "^5.15.11", "@resuwords/shared-components": "*", // Install shared components here "axios": "^1.6.7", "gatsby": "^5.13.3", "react": "^18.2.0", "react-dom": "^18.2.0" } }
Now, you can use the shared Button component in both Gatsby projects. For example, in project-one
import React from 'react'; import Button from 'shared-components'; const IndexPage = () => ( <main> <h1>Welcome to Project One</h1> <Button onClick={() => alert('Button clicked!')}>Click Me</Button> </main> ); export default IndexPage;
Repeat the same process in project-two.
-
Building and Copying Build Files
Now that we have our projects set up, let’s configure the build and deployment process.
-
Building the Projects
Run the build command for both Gatsby projects
cd packages/project-one npm run build cd ../project-two npm run build
-
Copying build files of the project-two to the project-one
In the, project-two’s package.json file’s build script should be like below.
{ "name": "project-two", "version": "1.0.0", "private": true, "description": "Gatsby project-two", "author": "", "scripts": { "develop": "gatsby develop", "start": "gatsby develop", "build": "gatsby build --prefix-paths && xcopy public\\* ..\\project-one\\public\\project-two /E /I /Y", "serve": "gatsby serve", "clean": "gatsby clean" }, "dependencies": { "@emotion/react": "^11.11.4", "@emotion/styled": "^11.11.0", "@mui/icons-material": "^5.15.11", "@mui/lab": "^5.0.0-alpha.166", "@mui/material": "^5.15.11", "@resuwords/shared-components": "*", // Install shared components here "axios": "^1.6.7", "gatsby": "^5.13.3", "react": "^18.2.0", "react-dom": "^18.2.0" } }
The build script provided is designed to work on Windows using the xcopy command. Here's how it works and how you can achieve the same result on Ubuntu or other Unix-like operating systems.
Windows (Using xcopy)
"build": "gatsby build --prefix-paths && xcopy public\\* ..\\project-one\\public\\project-two /E /I /Y"
xcopy is a command-line utility in Windows that allows copying files and directories, including subdirectories and hidden files.
The xcopy
public\\* ..\\resuwords-web\\public\\project-two /E /I /Y
part of the script./E
: Copies all subdirectories, including empty ones./I
: Assumes that the destination is a directory./Y
: Suppresses confirmation prompts to overwrite files.
This setup works perfectly on Windows environments, but xcopy is not available on Ubuntu or other Unix-like systems.
Ubuntu (Using cp)
To achieve the same functionality on Ubuntu, you would replace xcopy with the cp command, which is used to copy files and directories.
Here’s how you can modify the build script for Ubuntu
"build": "gatsby build --prefix-paths && cp -r public/* ../project-one/public/project-two"
cp -r public/* ../resuwords-web/public/project-two
- cp is the Unix command to copy files and directories.
- -r (or
--recursive
) tells cp to copy directories recursively, including all files and subdirectories. public/*
selects all files and subdirectories in thepublic
directory.../project-one/public/project-two
is the destination where the files should be copied.
-
Building the Projects
-
Building the Projects
With everything set up, you can now build your projects. Run the build script to build both project-one and project-two. The build files of project-two will be copied into the project-one project to be served under the same localhost port.
npm run build
-
Serving Both Projects Under One Localhost Port
After copying project-two’s build files to the project-one’s public folder, to serve both projects under a single localhost port, we’ll use the
gatsby serve
command for project-oneYou can now access both projects by navigating to.
http://localhost:8000/
for project-onehttp://localhost:8000/project-two/
for project-two
This approach allows you to run both projects under one port, creating a seamless user experience and simplifying local development.
Conclusion
In this blog post, we have seen how to configure a monorepo with two Gatsby projects and a shared component library using npm. By copying one project’s build files into another, we are able to serve both projects under one localhost port. It is a specially useful technique in projects which need to interact closely with one another but still maintain a modular, scalable architecture.
Having a monorepo can yield great benefits whether you are building a multi-site platform or just want to ease your development life. If you’re working on similar setups or have questions-please share your thoughts in comments!