A monorepo, or monolithic repository, is a setup where multiple packages (those dependencies that you typically list in a package.json
file and install with pnpm install
) reside within a single, unified code repository.
This structure is beneficial when managing different components, like connectors, that are used across various projects or applications, which we'll refer to as 'shops' in this context. Each of these shops may also be considered as separate packages within the monorepo.
In a monorepo setup, if we make a change to a particular component, such as a connector, we don't have to update all the shops simultaneously. Instead, we can selectively update only those shops that use or depend on the changed component.
This provides better control over code updates and allows us to maintain different versions of components for different shops, even though all the components and shops reside within the same repository. This structure can simplify code management, especially in large-scale projects where components are shared among multiple applications or services.
Our setup looks like this:
Folder | Description |
---|---|
<root> | Contains the root package.json file. Only has prettier |
packages/eslint-config | Contains the shared config for eslint |
packages/connectors/contract | This is the contract that the shops use and that the connectors must fulfill |
packages/connectors/<connector> | Contains the connectors |
packages/shops/<shop> | Contains the shops |
You should not use any of the npm
commands but always pnpm
.
Installing a package for a certain package in the repo would be pnpm add --filter kaufland-demo <package>
. To get started you could do pnpm install -r
, which would install all packages recursively.
To add a new package within the monorepo, you need to create a new directory under the appropriate directory (packages/connectors
for connectors, packages/shops
for shops). The name of the directory should be the name of your new package.
Inside this new directory, you need to initialize a new package with pnpm init -y
. This will create a package.json
file with default values. You can then edit this file to specify the details of your package.
Here's an example of how to add a new connector:
cd packages/connectors
mkdir my-new-connector
cd my-new-connector
pnpm init -y
After this, you can start adding your code in the new package directory. Remember to add any new dependencies that your package needs directly to its own package.json
file, not the root package.json
.
When your package is ready, you can make it available to other packages in the monorepo by running pnpm install -r
from the root directory. This will create a symlink in the node_modules
directory of the other packages, allowing them to import your new package as if it was installed from the npm registry.
You should not use relative paths import algolia from '../connectors/algolia'
when accessing a package from another workspace package but rather use import algoia from '@etribes/algolia'
.
Dependencies in package.json
to other packages in the repo should be expressed as workspace:<version>
, so for example:
"@etribes/connector-contract": "workspace:0.0.1",
This causes pnpm to only use packages from the repo and not download them from the Gitlab repository. If the specified version is not found in the repo, pnpm will throw an error.
pnpm
instead of npm
to ensure that the monorepo structure is respected.workspace:<version>
when adding a dependency to another package in the monorepo.pnpm install -r
to ensure that all packages are up to date and the symlinks are correctly set up.Powered by Doctave