Prepare standalone directory to deploy package in a monorepo using npm workspaces
Asked Answered
L

1

7

I have a monorepo that uses npm workspaces.

root/
  app/
    package.json
  server/
    package.json
  store/
    package.json
  utils/
  package.json

The app/package.json file references private non-published dependencies in its package.json like this:

{
  "dependencies": {
    "@my-scope/server": "file:../server",
    "@my-scope/store": "file:../store",
    "@my-scope/utils": "file:../utils"
  }
}

This is working fine when running locally; npm hoists all the node_modules dependencies to the top of the repo and adds symlinks between our dependent packages. However, things break once I try to produce a .zip file archive for deploying to Azure. I of course don't want to deploy my entire monorepo, just my app package. However, with all the node_modules dependencies hoisted up to the parent directory, this won't work.

I've tried running this inside of the app directory:

npm install --workspaces=false

It produces this which is close to what I'm looking for:

app/
  node_modules/
    direct-dependency-a/
    direct-dependency-b/
    @my-scope/
      server/ -> ../../../server
      store/ -> ../../../store
      utils/ -> ../../../utils

...but it does not install any of the dependencies of the @my-scope/* packages.

How can I produce a completely standalone deployment-ready directory from a npm workspaces monorepo?

Latinism answered 25/6, 2023 at 21:33 Comment(1)
I would expect this to be a common scenario, but googling for examples is nearly impossible.Onus
L
3

I found the key. In addition to running an install with --workspaces=false, adding the --install-links option to the npm install command causes the packages to be installed correctly. It copies the files from the monorepo package instead of linking, and it installs its dependencies as well.

Caveat: as @RafaelLeite points out in the comments, this doesn't use lockfiles since your lockfile is hosted at the root of the monorepo, and that can cause "unsupervised" version bumps when installing, so this is still not a perfect solution.

Latinism answered 25/6, 2023 at 22:1 Comment(4)
The problem with this approach is that it only works with npm install, not npm ci - which is usually what one would want on CI so its using the exact same versions from the package-lock.json file. But for whatever situation npm install is acceptable, this option is great!Derr
Yes, very true, and it's definitely a problem, getting unsupervised version bumps. If you have a good solution that works with npm ci I'd love to see it. I wonder if each of these packages had their own shrinkwrap files if that would work around it...Latinism
Hi, this answer helped me get started to create an aws lambda function that is part of a monorepo. Are you using typescript by any chance? I'm currently stuck with the fact that the dependencies arn't being compiled. It seems like the install isn't running 'prepare' in this scenario.Membranous
@Membranous I build lambda functions in a monorepo with typescript. My package has a build script that launches rollup -c. My rollup.config.mjs file uses these standard rollup plugins: json, commonjs, nodeResolve, and typescript. I came here to see if anyone knows how to build a .zip file from my "dist" folder.Bent

© 2022 - 2024 — McMap. All rights reserved.