What is Monorepo
Monorepo is a way to manage project code by managing multiple modules/packages in a project repository (REPO), as opposed to the usual repO for each module.
├ ─ ─ packages | | ├ ─ ─ two packages pkg1 | | | ├ ─ ─ package. The json | | ├ ─ ─ pkg2 | | | ├ ─ ─ package. The json ├ ─ ─ package. The jsonCopy the code
Implement a simple JS Monorepo project using Yarn Workspaces
Create a project directory
Create a folder called monorepo
mkdir monorepo
Copy the code
Initialize the project
Initialize YARN in the monorepo directory
yarn init
Copy the code
The package.json file should appear in the monorepo directory
Configuration Yarn machine-specific
Modify the code in the /monorepo/package.json file as follows
{
"name": "monorepo"."version": "1.0.0"."license": "MIT"."private": true."workspaces": [
"packages/*"],}Copy the code
Private :true: defines this project as a private project. When using yarn Workspace, you must always set the private property to true.
Workspaces: Defines the location of each package. In this project, we will place each package in the Packages directory. Note that this property is an array of strings, and we can add as many bits as our project needs.
Create packages directory
Create the Packages folder under the Monorepo directory to hold our packages
mkdir packages
Copy the code
Initialize the package – a
In /monorepo/ Packages /, create folder package-a and initialize YARN
cd packages
mkdir package-a
cd package-a
yarn init
Copy the code
We can follow the monorepo naming convention and name it @monorepo/package-a in package.json
The development package – a
At this point, we are ready to start developing Package-A.
As a demonstration, we can create a new main.js file under package-a and add the following code
// index.js
console.log("This is a package - a");
Copy the code
Initializes the package – b
Create folder package-b under /monorepo/ Packages/and yarn is initialized. Step with the package – a
The development package – b
At this point, we are ready to start development on Package-B.
As a demonstration, we can create a new main.js file under package-b and add the following code
// index.js
console.log("This is a package - b");
Copy the code
Reference package-a in package-b
A big advantage of Monorepo is that different packages under the same Monorepo project can refer to each other.
Suppose we have three React apps under our Monorepo project. Each React App requires the same line chart component. At this point we can:
- Each React App develops its own line chart component. This, however, creates duplication of effort, and in the future three line chart components will be maintained simultaneously.
- Develop a line chart component in one React app, and then copy it in the other two React apps. This eliminates repetitive development, but three React App line chart components still need to be maintained when the line chart components need to be changed.
- Create a line chart package and reference it in the three React Apps. Thus, we only need to develop and maintain the line chart Package.
At first, we need/monorepo/packages/package – b/package. Add dependent package – a json.
{
"name": "@monorepo/package-b"."version": "1.0.0"."main": "index.js"."license": "MIT"."scripts": {
"dev": "node index.js"
},
"dependencies": {
"@monorepo/package-a": "1.0.0"}}Copy the code
Then in/monorepo/packages/package – b/index. Js refer package – a
// index.js
require("@monorepo/package-a");
console.log("This is package-b");
Copy the code
Note that running index.js under package-b will cause an error because package-a is not installed yet, although we reference it in dependencies. Therefore, we need to run YARN or YARN Install.
At this point, we run the index.js file under package-b again, and we see the following output
$ node index.js
This is package-a
This is package-b
Copy the code
Introduce TS and React
Let’s introduce TS and React in the Monorepo project
Create the React App
In the /monorepo/ Packages directory, execute
yarn create react-app client --template typescript
Copy the code
Then, you can go to the client directory and start react to verify that the installation is successful
cd client
yarn start
Copy the code
Create Interface package
Assuming we do full stack development with TS, a common requirement is that the interfaces of the front and back apis should be shared.
So here we create a package to share the interface
First, we create a new folder interface under the /monorepo/ Packages/directory
mkdir interface
Copy the code
Next, we initialize the YARN project yarn Init under interface
Next, we initialize the TS project TSC –init
Json “declaration”: true “outDir”: “./dist” “rootDir”: “./ SRC”
Finally, we modify the package.json file as follows
{
"name": "@monorepo/interface"."version": "1.0.0"."main": "dist/index.js"."types": "dist/index.d.ts"."license": "MIT"."scripts": {
"build": "tsc"}}Copy the code
The development of interface package
Under the interface directory, we can create the SRC directory and create index.ts under the SRC directory
Declare an interface in index.ts
// index.ts
export interface MyAPIResponse{
msg: string
}
Copy the code
At this point, we convert the TS code into JS code YARN Build in the interface directory
We can see a new dist folder in the Interface directory to save our built JS files.
Reference the Interface Package in the React project
Add dependencies to package.json in the React project
"@ monorepo/interface" : "1.0.0"Copy the code
The installation depends on YARN or YARN Install
This way we can reference the interface defined in the Interface Package in the React project. As in the SRC/App. The TSX
import { MyAPIResponse } from "@monorepo/interface";
Copy the code
Noreactive and global Package
nohoisting
All dependencies in monorepo are stored in node_modules at the root: /monorepo/node_modules
But in some cases, we may need different versions of the same package. For example, a React project is older and uses Bootstrap 4. Another new project in development decided to use Bootstrap 5.
At this point we need to modify the package.json file in the root directory
{
"name": "monorepo"."version": "1.0.0"."license": "MIT"."private": true."workspaces": {
"packages": [
"packages/*"]."nohoist": [
"**/bootstrap"]}}Copy the code
As you can see, our workspaces has a new nohoist property, where we can add the names of packages that do not need to be shared.
Install global Package
Prettier can be installed in the root directory of a project where prettier is needed to format code
yarn add prettier -W
Copy the code
Here we use W flag to have yarn Workspace install dependencies in the root directory.
conclusion
This article introduces some basic concepts and implementation methods of YARN Workspaces MonorePO.
In practical work, lerna and other tools can be combined to build our MonorePO project.