I have a small monorepo with a few projects (they share the same data stores, so it's easier to have them together in a monorepo for development and testing). Each project is in its own folder, with its own package.json. Each project is meant to be deployed on its own (independent of the other projects).
I would like to share some code between the projects. I want to maintain their relative independence, so I'd rather not have to create a "build" step in the root repo folder, as well as having each project's own build step. Ideally deployment of each project would continue to be done in the project's folder, without it needing to know about other projects.
I know I could create an npm module in the repo and npm link
to it from each project. This is the solution I'm leaning toward. But I'm wondering if anyone has a better idea.
Here's an example of what the directory structure kinda looks like:
/package.json
/docker-compose.yml
/project-1/package.json
/project-2/package.json
If I went with the npm link
solution, I would add something like a project-shared
folder and link to it from project-1
and project-2
.
This is the npm link solution I'm using at the moment. It seems like an OK solution, so I thought I'd post it as an answer. I haven't yet implemented the deployment stuff for this project, so I don't know how well deployment will work with this. I'm hoping it will deploy the linked module along with everything else.
The project directory structure looks like:
/package.json
/docker-compose.yml
/project-1/package.json
/project-2/package.json
/project-shared/package.json
In each project's package.json (project-1
and project-2
), I added this postinstall script:
"scripts": {
"postinstall": "npm link ../project-shared"
},
So the link will be created during the normal setup of the project.
NOTE: For some reason this doesn't work using a preinstall
script (the link won't be created, though it looks like it's run). postinstall
works just fine.
I'm not quite sure how dependency installation works for the shared module (e.g. if the shared module's dependencies will be installed when the projects link to it, or if I'll have to install them independently).
One problem I encountered is that Docker Compose doesn't play well with linked packages (the symlinked folder won't point to the correct location inside the container). I fixed this by mounting the shared folder over the symlink in the node_modules folder. For example, for project-1
:
volumes:
- "./project-1/:/home/node/app:ro"
- "./project-shared/:/home/node/app/node_modules/project-shared:ro"
EDIT: Sept 4, 2020
Wanted to drop a note that I've been using this in production for a while and it works great. One issue I've noticed in dev, with the shared library mounted in the Docker container, is when you npm install
from your host computer it will run postinstall
and symlink your shared library folder. This is expected, except in Docker it messes up your mount. The solution I've found is to stop Docker, remove the link, re-create the folder, and start up Docker again. A better solution might be replacing your postinstall
script with something like this:
"postinstall": "test -d node_modules/project-shared || npm link ../project-shared"
This will only link the folder if it doesn't already exist. I've only tested this a little bit, so I'm not sure if I'm missing any weird edge cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With