PNPM workspace with git submodules
Introduction
We published quite a few open-source packages on NPM.
Developing multiple NPM packages that rely on each other is not easy task. There are a lot of ways that things can go wrong: keeping stuff in sync, publishing etc.
We tried a couple of other tools to solve this problem: git repo npm modules, npm link and yalc so far but no of them was as good as pnpm.
Our go-to method now is a pnpm workspace monorepo with git submodules. Very convenient solution for projects with multiple separate git repositories.
Features
pnpmmakes it convenient to manage and develop multiple separate packages without using any other tools likenpm linkoryalc- easy to publish and takes care of updating dependencies using
changeset - recursively remove
node_modules,dist, or build your projects
How to use it
Follow this step-by-step guide on to create a pnpm monorepo with git submodules. All you need is a terminal.
Setup pnpm
1# create a new directory and cd into it 2mkdir mono-repo 3cd mono-repo 4 5# creates a package.json file 6pnpm init 7 8# creates an empty git repository 9git init
- do your usual setup (like add a
.gitignorefile etc.)
Monorepo structure
in this example there will be 2 folders apps and packages
appsfor acreate-react-app, which will consume packagespackagesfor several git submodules, each of them is a separate git repo, which are reusable packages- this structure can be defined in the
pnpm-workspace.yaml
1# pnpm-workspace.yaml 2packages: 3 # executable/launchable applications 4 - 'apps/*' 5 # all packages in subdirs of packages/ and components/ 6 - 'packages/*'
Git Submodules
add your submodules
1# add your submodules in the packages folder 2cd packages 3git submodule add https://github.com/<user>/rock rock 4 5# this will tell git to download the contents of the submodules, if the folders are empty 6git submodule update --init --recursive
- keep in mind that submodules are still separate GitHub repositories
- review changes, commit and push inside the submodules
- the root of the project is also a git repository which sees each submodule as a particular commit hash
- when a submodule has a new commit, the new commit hash can be staged and committed in the root project, so everyone else sees that the particular submodule now points to a new commit hash
Create react app
the following cra will live in the apps folder and will be part of the root, not a separate git repository
1cd apps 2npx create-react-app example
- the cool part of pnpm workspace is that the
examplereact app can use the submodules as dependencies - if the version numbers match, then the example app will use the built package from the
packagesfolder, otherwise pnpm will fetch it from remote npm registry (if it is published), workspace protocol
pnpm import
pnpm import generates a pnpm-lock.yaml from another package manager's lockfile
1# cd into a submodule 2rm -rf node_modules 3pnpm import 4# now remove the other package managers lockfile 5 6# go back to the root and install dependencies 7pnpm install
Release workflow
Long story short, pnpm does not version packages so when the time comes to publish a submodule to npm, some other tool needs to be used for that
- luckily changset takes care of it
1# add changeset in the root as devDependencpnpm add -Dw @changesets/cli 2 3# run the init command 4pnpm changeset init 5 6# generate a new changeset 7# the following command will ask which packages should get a new version 8pnpm changeset 9 10# this will bump the versions previously specified with pnpm changeset 11pnpm changeset version 12 13# update lockfile and rebuild dependencies 14pnpm install
- changeset also takes care of the
exampleReact app, and if any of its dependencies has a new version, it will update thepackage.jsonversion of that package
Running workspaces
- workspaces can be run separately with the
--filtercommand - or all of them at once with the
--recursivecommand
1# build only one project 2pnpm --filter <package> run build 3 4# run all of them at once 5pnpm -r run build
Conclusion
- we use
pnpmworkspace in suggestcat-repo,suggestcatis a set ofProseMirrorplugins, which gives AI suggestions - with
pnpmworkspace we can developsuggestcateasily, because we have 4 different submodules which depend on each other, and our React app with the ProseMirror editor consumes all of those packages, without a monorepo we would have to publish to npm registry all the time we change something in any of the repos, or usenpm linklocally, which is quite cumbersome, or some other tools likeyalcwhich seemed to be working just fine for the first time, but with 4 packages it needed to be restarted all the time


