https://github.com/joelparkerhenderson/monorepo-vs-polyrepo
Preinstall
$ npm i -g pnpm
$ pnpm -v # should >= 6.20.0
# To use native code in your project, please install Rust and Cargo.
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Please be patient as the installation of dependencies may take some time.
$ pnpm install
apps
- Apps that only use packages and aren't aware of other apps.packages
- Packages that may use other monorepo packages.
1.A common scenario for using a Monorepo is when multiple packages, such as a client and server, need to be released together, Monorepo makes the release process of these packages more convenient.
# Start React App
$ pnpm --filter "react-app" start
$ pnpm --filter "node-app" start
2.If different packages need to share common code
To address the reuse of enumerations, configurations, and utility methods, we aim to make them available for use in all projects.
Here is how to use it:
Declare the module's dependency in the project, where workspace:* indicates the use of the current Monorepo's shared module package.
// apps/*/package.json
{
"dependencies": {
"@infras/shared": "workspace:*"
}
}
To facilitate convenient debugging of Monorepo package modules, we'll use the pnpm workspace protocol (which is also supported by yarn). In the project, use the following:
Import using the esm format Require using the cjs format Utilize commonly used project configuration tsconfig.json
// apps/*/index.{ts,tsx,jsx}
import { AppType } from '@infras/shared/types';
import { sum } from '@infras/shared/utils';
console.log(AppType.Web); // 1
console.log(sum(1, 1)); // 2
// apps/*/index.js
const { AppType } = require('@infras/shared/types');
const { sum } = require('@infras/shared/utils');
// apps/*/tsconfig.json
{
"extends": "@infras/shared/configs/tsconfig.base.json"
}
$ pnpm --filter "@infras/shared" dev
$ pnpm --filter "@infras/ui" dev
3.Module packages written in native languages (Rust / C++ / Golang, etc.). We can use npm package modules written in Rust / Golang within a Monorepo to handle CPU-intensive tasks.
$ pnpm --filter "@infras/native" build
Usage:
Declare the dependency on the native language module in the project.
// apps/node-app/package.json
{
"dependencies": {
"@infras/rs": "workspace:*"
}
}
Calling it in Node.js:
// apps/node-app/index.js
const { sum } = require('@infras/rs');
console.log('Rust `sum(1, 1)`:', sum(1, 1)); // 2
// apps/node-app/index.mjs
import { sum } from '@infras/rs';
Building it as cjs:
Here, we use napi-rs to initialize an npm package built with Rust. napi-rs doesn't build an esm format package but instead chooses cjs format for compatibility with esm (related to node#40541).
# packages/rs
- src
- lib.rs
- npm
- index.js
- index.d.ts
- package.json
- Cargo.toml
package.json:
We directly use the package.json generated by napi-rs without any modifications.
{
"name": "@infras/rs",
"version": "0.0.0",
"type": "commonjs",
"main": "index.js",
"types": "index.d.ts",
"devDependencies": {
"@napi-rs/cli": "^2.0.0"
},
"scripts": {
"prepare": "npm run build",
"artifacts": "napi artifacts",
"build": "napi build --platform --release",
"build:debug": "napi build --platform",
"version": "napi version"
}
}
Running:
In the Node project, run pnpm start --filter "node-app". This way, you can observe that the Rust-compiled function is much faster than the nodejs.
js implementation (8.44ms → 0.069ms).