I currently am developing a TypeScript shared library. The library needs to be imported in sections to minimize the imported bundle size, so I broke it up into packages with a monorepo with Lerna. Things are going great. Each package has its own dist folder and each of those are published to the GitHub artifact store for consumption by other applications. The expectation was that I'd unit test the library and any updates would be published as new versions to this store.

But a new requirement is shaking things up. Normally if I'd like to develop a library in tandem with the application that's consuming it, I'd provide a local URL to the package.json. But for a mono repo, this doesn't work. The URL points to a different file structure than what is expected.

This is leading to all kinds of headaches. The host applications are dockerized, so it's leaning to over-complicated solutions like Rsyncing over the files, setting up custom volumes and build locations, or literally copy pasting the library's source into the host app for momentary use.

I feel like I'm reinventing the wheel here. What do other folks do for developing a mono repo library through other applications? My preference would be to just test the library well and then iterate as new requirements arise, but that's not an option anymore.

yarn: 1.22.9 node: 16.20 lerna: 6.5.1 typescript: 5.0.2

TypeScript is used for the build step. Lerna helps with having each different piece of the library be in a different packages folder. Each package has its own package.json, in which:

  • main : dist/index.js
  • types : dist/index.d.js
  • exports: .
  • exports/import: ./dist/index.js
  • exports/types: ./dist/index.d.js

2 Answers 2


I was faced with something similar last week, when moving a monorepo library and an application both to React 18. What I ended up doing was using the canary option in lerna to create a local alpha version, then npm pack in on each project to create a .tgz which I could install into the application rather than linking to the folder.

> lerna publish --canary

which will set the versions in package.json but fail to push the artifacts to Azure, so you need to package everything after running it:

> foreach ($package in Get-ChildItem -Path packages -Directory) {
   pushd $package.FullName
   npm pack

or equivalent if you're not using PowerShell.

Then install the libraries into the application you're developing using them with

npm uninstall my-libs-foo
npm install ..\my-libs\packages\foo\foo-0.83.3-alpha.3+2093oeeuc.tgz

Unfortunately if the libraries depend on each other you'll have to install all the dependencies in the same way in order.

Then, once the libraries are at their final version, uninstall the local packages and reinstall from the artifact repository.

  • This solution almost worked for me. But the yarn install step is inside a docker file for me, which means that the built .tgz files need to be set up as a volume. That part did work and I can docker-compose run --rm my-app yarn install mypackage and it does resolve. But then yarn will throw an error during docker-compose up saying that the SHA of the new tgz file has changed... somehow.
    – devleo
    Commented May 24, 2023 at 0:17

I am working in a C++ ecosystem where compiled copies of a library are picked up from an artifact store. And we also develop the libraries and the applications using them in tandem. I believe this is similar enough that you can get at least some ideas.

We have 2 mechanisms for referring to non-released versions of dependent libraries:

  • We can specify the dependency version as being "local". This means that the dependency resolution only looks at the artifact cache on the developer's local machine and picks the most recent local build. I am not sure if this is default functionality of our artifact store (Artifactory) or if it has been implemented as a customization.
  • Our build automation automatically stores a snapshot version of every branch that it builds in the artifact store.

This works well for us, but a third option to consider is that local builds get stored in the artifact store as snapshot builds. In all these cases, the difference with using a released version of the dependency is only in the version identification you specify.

Developing over an artifact store can take some getting used to, as you probably have to perform multiple steps to try out the latest changes in the library, but it doesn't have to be as bad as doing a full release every time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.