Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

peerDependencies not installed when lockfile exists #4988

Closed
robations opened this issue Jul 6, 2022 · 12 comments · Fixed by #4998
Closed

peerDependencies not installed when lockfile exists #4988

robations opened this issue Jul 6, 2022 · 12 comments · Fixed by #4998
Milestone

Comments

@robations
Copy link

pnpm version:

7.5.0

Code to reproduce the issue:

# .npmrc
auto-install-peers = true
strict-peer-dependencies = false

# workspace-main/package.json
...
  "peerDependencies": {
    "angular": "~1.7.9",
    "babel-loader": "^8.2.2",
    "core-js": "^3.10.2",
    etc
  }
...

# workspace-app1/package.json
...
  "dependencies": {
    "workspace-main": "workspace:*"
  },
  "dependenciesMeta": {
    "workspace-main": {
      "injected": true
    }
  },
...

(in my use case, up to 20 similar apps with the same kind of package.json as app1, hence not wanting to repeat the peer deps)

If this example isn't enough, I could create a minimal reproduction.

Expected behavior:

Whether the lockfile is present or absent, I expect the peer dependencies under "workspace-app1" to install automatically, if not already linked.

Actual behavior:

When the lockfile is absent, the peer dependencies under "workspace-app1" install automatically.

When the lockfile is present, the peer dependencies under "workspace-app1" are missing and generates module errors in builds.

Additional information:

  • node -v prints: v14.19.3
  • Windows, macOS, or Linux?: seen issue with macOS and Linux

Have also experimented with --no-frozen-lockfile and --frozen-lockfile but doesn't make a difference, the main thing is whether the lockfile is there at all.

May be related to #4378, #4625

Also considering whether this is a recent regression. I was using 7.2 until recently and didn't notice this issue on build servers etc, only when I merge the changes to switch to pnpm...

@robations
Copy link
Author

Seeing the same issue with 7.2.1. I'm guessing this didn't come to light due to dirty node_modules directories that contained hoisted packages from using yarn previously.

I'll try to make a reproduction repo.

@robations
Copy link
Author

@robations
Copy link
Author

My guess is that the problem is more with auto-install-peers than dependenciesMeta.injected. It seems like the "workspace-main" workspace in the example is being hard-linked as expected, just the auto-install isn't triggered.

Let me know if I can help or provide any more information.

@zkochan
Copy link
Member

zkochan commented Jul 8, 2022

There is an inconsistency but probably the auto installed peers should not be there even at the run without the lockfile.

If you check, lodash will be always linked to the real location of the injected dependency. The real location is inside node_modules/.pnpm.

@robations
Copy link
Author

@zkochan Thanks for your reply and time looking at this. No joke maintaining a package manager :)

probably the auto installed peers should not be there

Excuse my ignorance, but what is the point of auto-install-peers if the peers shouldn't be installed?

The use case is that I'm trying to avoid repeating the specifications (or at least to constrain them) for around 8 dependencies across ~16 workspace packages. (It's stuff like webpack loaders, gulp, angularjs.)

If I repeat the specs (by adding as direct dependencies to each workspace), this becomes a maintenance problem, because all the versions need to be kept in sync 🤯.

Before I used "injected" it just seemed like the peerDependencies were ignored within the workspace — versions not checked, not installed.

Not trying to flame, just hoping to get to a workable solution.

@zkochan
Copy link
Member

zkochan commented Jul 8, 2022

The peer dependency is installed. If foo has bar as a peer, it will be symlinked in the node_modules of foo:

node_modules
  foo --> .pnpm/foo@1.0.0/node_modules/foo
  .pnpm
    foo@1.0.0
      node_modules
        foo
        bar --> ../../bar@1.0.0/node_modules/bar
    bar@1.0.0
      node_modules
        bar

@robations
Copy link
Author

I was expecting (in my example repo) to be able to do:

cd workspace-app1 && node -r "lodash"
# or
cd workspace-app2 && node -r "lodash"

and see no error (because lodash is installed automatically).

Actual output is Error: Cannot find module 'lodash'

But maybe I misunderstand the meaning of "auto-install". It's hard to compare with npm behaviour because of its hoisting.

I also notice the same inconsistent behaviour with non-workspace packages:

mkdir new-project && cd new-project
echo auto-install-peers=true >> .npmrc
pnpm init
pnpm add react-dom
node -r "react"
# no error because react is installed directly in node_modules/react

# install again from lockfile
rm -rf node_modules
pnpm i
node -r "react"
# Error: Cannot find module 'react'

If your definition of peer deps + "auto-install" is correct, I'll have to find a more manual way to sync my dependencies between packages, or perhaps this could be a feature request for the future? auto-install-peers-direct=true perhaps.

@robations
Copy link
Author

Lol. I was reading https://github.com/npm/rfcs/blob/main/implemented/0025-install-peer-deps.md and yarnpkg/berry#1001 to try to understand this better.

Maybe something completely new is needed. Peer dependencies are already super complex.
— zkochan

I was thinking of peer deps as a solution to a problem, but perhaps better avoided!

@zkochan
Copy link
Member

zkochan commented Jul 8, 2022

cd workspace-app1 && node -r "lodash"

if you need to do this, you need to add lodash to your dependencies. Otherwise, you are relying on hoisting. If you want hoisting, use node-linker=hoisted.

@belgattitude
Copy link

belgattitude commented Jul 9, 2022

@robations @zkochan I haven't followed entirely.

My attention was caught by the rfc 25 you've mentioned.

. I was reading https://github.com/npm/rfcs/blob/main/implemented/0025-install-peer-deps.md and yarnpkg/berry#1001 to try to understand this better

This rfc was included in npm v7, but quickly made obsolete by

https://github.com/npm/rfcs/blob/main/implemented/0030-no-install-optional-peer-deps.md

And now the default for npm 8. (No auto install)

Few months ago, I researched a bit when having to choose between peer deps and deps.

Here's the summary

https://gist.github.com/belgattitude/df235dc0ca3929ef2b56eb26fe6f3bed

Hope it's useful.

@robations
Copy link
Author

robations commented Jul 11, 2022

Thanks @belgattitude for additional docs. I think the historical changes muddy the water of what was already a complex topic. And the differences between hoisting/not hoisting don't help :)

I think I was interpreting a peer dependency as:

I need this dep, and you need it such that we have the same version.

but it's maybe more like

I need this dep, and iff you also need it directly, you need to install it such that we have the same version.

@robations
Copy link
Author

@zkochan thanks for updates.

Yeah, I'm still trying to avoid hoisting. I've written a script to parse the peerDependencies from my "main" package.json and add them as direct dependencies to any package that has "main" in its dependency chain. Not ideal but reduces the maintenance burden a little.

@zkochan zkochan added this to the v7.5 milestone Jul 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants