How do I install dependencies for a single package when using npm workspaces?
Asked Answered
I

2

24

Using npm workspaces I have a folder structure like this

+-- package.json
+-- package-lock.json
+-- client
|   `-- package.json
+-- shared
|   `-- package.json
`-- server
    `-- package.json

Normally when creating a production build for a nodejs app I would run npm ci --only=production and then copy node_modules into a build artifact. I'm not sure how to do something like that when working with workspaces.

If I run npm ci --only=production --workspace server it splits the dependencies across ./node_modules and ./server/node_modules. Maybe I should copy (merge?) both node_modules into a build artifact?

Another option could be to copy ./package-lock.json and ./server/package.json into a fresh directory and run npm ci --only=production. It does seem to work but I don't know enough about npm to know if this is a good idea.

The requirements are:

  1. node_modules should only include production dependencies for the chosen package
  2. The dependency versions should be determined by package-lock.json.
Isis answered 31/12, 2021 at 7:47 Comment(3)
Did you ever figure out how to do this?Garnett
@ReedHermes I kind of got it working with npm ci --only=production --workspace server but it does mean the artifact has an extra directory level which is a bit annoying. I was having a few issues with npm workspaces like this github.com/npm/cli/issues/3847 so ending up dropping them for now.Isis
on the flip side, is there a way to only install root depencies in the root level package.json?Canicular
E
0

According to the available npm options I would suggest a combination of

So from the workspaces root:

npm install --install-strategy=nested --omit=dev --workspace=server

You may or may not need -install-strategy.

This should leave a node_modules directory at the root of the workspaces with only the dependencies defined in the server workspace's package.json file with those defined in devDependencies omitted. You can also --omit=peer to remove peerDependencies from the server workspace as well.

NOTE: Depending on your dependency graph, this could still leave multiple node_modules directories that would require combining to create the artifact, i.e. --install-strategy=nested does not appear to be working correctly for npm workspaces. However, the installed deps should correctly be isolated to the workspace passed in --workspace. Here is an example repo showing how those dependencies could be combined.

Earpiercing answered 31/5, 2023 at 19:20 Comment(2)
This doesn't work. Even with --install-strategy=nested, npm install splits the server dependencies between node_modules and server/node_modules. And even if it did work, it would have the downsides of the nested strategy (very deep directory structures, no de-duplicating).Pallaton
Nowhere does the question state root node_modules but only that all production dependencies be available in node_modules from within a monorepo so that later a build artifact could be constructed.Earpiercing
P
0

The split between node_modules and server/node_modules is due to hoisting. If there were a way to disable hoisting, then all dependencies of server would be installed to server/node_modules. However, current versions of npm do not provide a way to disable hoisting for workspaces.

There is discussion about adding such a feature in the following issues:

Pallaton answered 23/6, 2023 at 18:37 Comment(1)
There is already a nested install strategy so an option to not hoist seems redundant. However, the nested install strategy appears to be broken for workspaces: github.com/npm/cli/issues/6537Earpiercing

© 2022 - 2024 — McMap. All rights reserved.