In the previous post, I mentioned so-called workspaces. This is a good starting point which also will show how to structure your future and existing projects. The first one (starting without any projects) is easy, the second (existing ones) requires a bit more work but with a bit of luck, everything should run smoothly.
The below steps describe how to do this with pnpm. You could also use yarn berry or yarn classic. In such case this approach works slightly differently by adding such structure description to the package.json
file. The rest is quite similar.
Wait, but why not npm? I've heard that it also has workspaces.
AFAIK it's still not monorepo-ready due to serious problems with hoisting and the lack of ability to solve such dependencies. A good explanation of the struggle with npm caveats is provided in this article ;)
If you want to know more about creating a monorepo check out other tutorials in the series. If you prefer testing things on your own - try this template, where I put all of this into work.
Let's get to the work
-
Install pnpm if you don't have it yet:
npm install --global pnpm #or npm install --global corepack@latest corepack enable pnpm corepack use pnpm@latest-10
or you can follow the other options from the pnpm installation guide.
-
Create a new directory with a
package.json
file structured as follows:
{ "name": "your_company_or_so", "version": "1.0.0", "private": true, "dependencies": { // all repeating dependencies } // ... }
-
Add a
pnpm-workspace.yaml
file in the root directory to define your workspace structure:
packages: - 'apps/*' - 'libs/*' - 'whatever_else/*'
Add a bunch of sub-directories like
apps
,libs
, etc. as defined in your workspace file.Put your projects into the mentioned directories and/or create new ones.
Cut out the repeating
dependencies
anddevDependencies
from your projects'package.json
files in the sub-directories and place them in the rootpackage.json
file. These are now connected to all your projects - exceptions are possible (read below).Delete all your
node_modules
in the sub-directories if you copied them.-
As mentioned in the previous post, you can directly connect your libraries to the projects by modifying the app's
package.json
file like so (more on this in the next article):
{ "name": "@monorepo/app_1", "version": "1.0.0", "type": "module", "scripts": { // ... }, "dependencies": { "@monorepo/commons": "workspace:*", "@monorepo/ui": "workspace:*" }, // ... }
-
Go to the root directory and install dependencies for all the projects at once:
pnpm i
FAQ
What about the dependencies that are not identical?
First consider bringing them to the same version, preferably the newer ones.
It's too time-consuming right now.
I get it—deadlines, and so on. You can just leave them where they are. I would still strongly recommend having only one version of Vue, React, Typescript, etc., because the more packages tied to the same version, the easier it is to update all your projects at once and deal with refactors after updating all the projects in one go.
Fine, I updated what I could, but there are still some dependencies requiring different versions.
It's fine, there is nothing wrong with it. Decide which version is more common and move this one to the root package.json
. The less common version will stay in the package.json
file of the project that is using it. This way, you signal your package manager that you need that specific version in a particular project, and it will be installed independently.
What about dependencies that are used only once? Should I move them as well?
It's up to you. If you assume that they will be used more often, sure, move them. Are they used only once for this specific project, and it's highly unlikely that it will change? Nah, you don't have to move it and pollute the root package.json
.
Adding new dependencies
If you need to add something new to your monorepo you have two options:
-
Install a package for the entire workspace - run it in the root directory
# for dependencies pnpm add <package-name> -w # for devDependencies pnpm add <package-name> -Dw
-
Install it only for one of the apps / libs - run it in the app / lib directory
# for dependencies pnpm add <package-name> # for devDependencies pnpm add <package-name> -D
Troubleshooting
I have some problems with dependencies with different versions.
You can try omitting this one migration to the root package.json
file and keeping it in the projects' package.json
files instead.
If you want to learn more about creation of monorepo with Vue, check out other tutorials in the series. If you prefer starting with a solid foundation - try this template, where I’ve put all of this into practice.
Top comments (0)