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

Add a means to install package peer dependencies for development / testing #1503

Closed
jshthornton opened this issue Oct 27, 2016 · 79 comments
Closed

Comments

@jshthornton
Copy link

@jshthornton jshthornton commented Oct 27, 2016

Do you want to request a feature or report a bug?
Feature

What is the current behavior?
N/A

What is the expected behavior?
Provide a CLI command yarn install --peer which will install peer dependencies specified in package.json. That way development / testing can use the peers such as react/ng2/grunt.

@jshthornton
Copy link
Author

@jshthornton jshthornton commented Nov 9, 2016

@jpollard-cs I am not referring to adding a package as a peer dependency, I am referring to having a means to install all packages currently listed as peer dependencies.
Otherwise there is not a viable means of developing plugins.

@esutton
Copy link

@esutton esutton commented Nov 9, 2016

npm install
Would install all packages declared in package.json dependencies section.

yarn add --peer
I expected this to install all packages declared in package.json peerDependencies section.

Is there a way to install a declared packages in peerDependencies?

My use case is development / testing of a react native module.

@oliverjanik
Copy link

@oliverjanik oliverjanik commented Nov 29, 2016

Here's NPM issue, which they closed: npm/npm#11213

Apparently not important to NPM devs.

@gf3
Copy link

@gf3 gf3 commented Jan 30, 2017

+1 this is important for library authors

@nathanhleung
Copy link

@nathanhleung nathanhleung commented Mar 10, 2017

I already wrote this on the NPM issue, but for Yarn people:

I wrote a cli program install a package's peer dependendencies:

# If you're using npm
npm install -g install-peerdeps

# If you're using yarn
yarn global add install-peerdeps

cd my-project-directory

install-peerdeps <package>[@<version>]

# for example
install-peerdeps @angular/core
# will install all of angular's peerdeps

If you have any problems with it please open an issue on the repo!

@jshthornton
Copy link
Author

@jshthornton jshthornton commented Apr 11, 2017

@nathanhleung, that package appears to install all of your dependencies peer dependencies. Which isn't quite what this ticket is about. This about installing your own package's peer dependencies.

I have fixed it with a package to do that https://www.npmjs.com/package/@team-griffin/install-self-peers

@LyzioOh
Copy link

@LyzioOh LyzioOh commented May 1, 2017

@nathanhleung you rocks.

kohlmannj pushed a commit to kohlmannj/jss-simple that referenced this issue May 5, 2017
@nikolakanacki
Copy link

@nikolakanacki nikolakanacki commented May 15, 2017

Hmm... If one needs dependencies for development / testing, shouldn't one put them under devDependencies? Not trying to drop a bomb or anything...

@keyboard-clacker
Copy link

@keyboard-clacker keyboard-clacker commented May 22, 2017

@nikolakanacki Totally see where you're coming from, I think the weirdness is that it'd be both a peer dependency and dev dependency, since you should never force your consumers installing your dev dependencies. I vote making it easy to install peers!

@alexilyaev
Copy link

@alexilyaev alexilyaev commented Jun 12, 2017

@nikolakanacki If you author a package that relies on another package that the user installs, you don't want it in devDependencies, that may result in a duplicate of that package in a different version., and won't makes sense in some cases...

Use case eslint-find-rules

The package looks up rules available in ESLint that are not configured in your config.
For it to make sense for a user, it needs to check the ESLint package they installed, and not some specific version your package comes with (or latest).
So, it's a peer dependency.

Now if you want to contribute to the project, you want to have ESLint installed in node_modules so you can test your code, without doing some npm-link with a dummy project that installs ESLint.

When the user runs yarn, the system should not install peer deps and warn they're missing (this works).

So... a flag that makes yarn install peer deps if they're not already installed would kindly solve that problem.

Interesting point

  • yarn add <package> --peer installs it to node_modules and adds it to package.json
  • yarn add <other_package> after that removes the installed package from node_modules
@gaastonsr
Copy link

@gaastonsr gaastonsr commented Jul 6, 2017

I'm currently following @nikolakanacki model and it seems to work. I agree it can be confusing and I would prefer a yarn install --peer to install dependencies, devDependencies and peerDependencies but this works just as good to me.

@nikolakanacki
Copy link

@nikolakanacki nikolakanacki commented Jul 10, 2017

If I'm getting this right @kyleholzinger / @gaastonsr, you're not looking to install peerDependencies in development mode (cd-ed into the repo / package which has peerDependencies, fresh clone, need to develop on those peer deps) but add them to the target project once you install the package which has peer deps?

To clarify: You install eslint-find-rules which complains that you need eslint as a dependency (it's a peerDependency of eslint-find-rules), so now you want an easy way of adding those dependencies in the peer you're working on (current project which depends on eslint-find-rules)? Something like "Resolve and add as new dependencies (modify package.json and yarn.lock) best matched peer dependencies my current dependencies require"?

If this is your point it could be super useful, I thought that you were referring to auto-installing them when developing.

The feature could be introduced for more then pure convenience, for example: multiple dependencies could depend on the same package from the peer target, but require different versions of it - this feature could make the best of it by trying to resolve to a single best-matching target (if possible).

Something to think about definitely.

@gaastonsr
Copy link

@gaastonsr gaastonsr commented Jul 10, 2017

If this is your point it could be super useful, I thought that you were referring to auto-installing them when developing.

This is what I'm looking for. Installing peerDependencies when I'm developing a package.

@keyboard-clacker
Copy link

@keyboard-clacker keyboard-clacker commented Jul 10, 2017

Yeah exactly @nikolakanacki! I feel like there's a great opportunity for us to help people out with managing their peer deps.

@nikolakanacki
Copy link

@nikolakanacki nikolakanacki commented Jul 10, 2017

@gaastonsr need to add it to devDependencies then - it's as simple as that. Your package is broken for development otherwise. Once you clone the project and run yarn - everything should be installed and you should be able to run tests, etc.

Two simple and totally unrelated questions one should ask before installing said dependency in cases like this:

  1. My package depends on this package, but I expect the target project to include it since my package is just a plugin for that package: Put it in peerDependencies.
  2. I have tests that depend on this package but it is not listed in my dependencies (and should not be listed there) for whatever reason: Put it in devDependencies.

In other words: All the packages which are expected to be present during development and are not listed as a direct dependency of the package being developed should reside in devDependencies. Duplicates are not an issue - nowhere in the docs does it states that dupes are not allowed / encouraged in these cases.

@alexilyaev
Copy link

@alexilyaev alexilyaev commented Jul 10, 2017

@nikolakanacki When we build a plugin for a package we should depend on the installed package version by the user, if we add it as a devDependency, we'll inevitably install a different version and it will be used instead of the user's version.

Unless we defined the dependency as *, but then Yarn should be somehow deterministic and prefer the user installed package instead of ours.

Currently it's not so:

@gaastonsr
Copy link

@gaastonsr gaastonsr commented Jul 10, 2017

@alexilyaev I think @nikolakanacki means to install it both as a peerDependency and devDependency.

This has the problem that we need to keep both in sync. For me it works good for now but I don't think it's ideal.

@nikolakanacki
Copy link

@nikolakanacki nikolakanacki commented Jul 10, 2017

@alexilyaev when you declare a peerDependency you declare its version as well. Unless target project has the version of that peer dependency installed which also satisfies the version you defined - yarn / npm will report an error (missing peer dependency, something like that).

Non the less devDependency has nothing to do with it, it is the one getting installed when running yarn or npm install inside the source package (the one declaring a peer dependency, eg: a plugin), and it is not even consulted when the package is being used by a third party package / project (a peer).

The point is: I don't see how all this is relevant?

@nikolakanacki
Copy link

@nikolakanacki nikolakanacki commented Jul 10, 2017

I can see the pain of keeping them in sync, but you could easily write a bash / javascript / <whatever> script that would check this as a post-install step in the package.json.

The point I'm trying to make is that in no way should we break the devDependencies sentiment, or worse yet introduce "running yarn or npm install does not necessarily installs all the required dependencies of this package" concept.

On the other hand yarn introduced an even more strict policy when it comes to this, it clears up the packages not otherwise defined as dependencies or devDependencies so you don't run into issues later on.

@alexilyaev
Copy link

@alexilyaev alexilyaev commented Jul 10, 2017

@nikolakanacki Let's say my plugin accepts ^7.0.0 and the latest of the peer is 7.9.0 and the user defined in their package.json 7.4.0.
if I'll have ^7.0.0 in devDependencies as well, wouldn't Yarn install (for the user) both 7.9.0 and 7.4.0?

If it does, my plugin might mistakingly use the installed 7.9.0 instead of 7.4.0.

@nikolakanacki
Copy link

@nikolakanacki nikolakanacki commented Jul 10, 2017

@alexilyaev Your package will always, as any other package in any other case, use the highest available version which satisfies the "semver range" defined in your package for this peer dep.

I'd be more specific but I don't quite understand the case you've presented, could you please clarify?

@gaastonsr
Copy link

@gaastonsr gaastonsr commented Jul 10, 2017

It will warn you that you have a peerDependency incompatibility, your plugin expects ^7.0.0 and you have version 7.4.0. Updated: ^7.0.0 satisfies 7.4.0.

wouldn't Yarn install (for the user) both 7.9.0 and 7.4.0?

Yarn doesn't install peerDependencies for you and won't install the devDependencies of your plugin just the dependencies in dependencies.

@nikolakanacki
Copy link

@nikolakanacki nikolakanacki commented Jul 10, 2017

@gaastonsr you're absolutely right except that ^7.0.0 is satisfied by 7.4.0.

Peer dependencies never get installed, dev dependencies do not get installed by default if the package is not the main package. The "end-user" needs to define which peer dependencies it want's to satisfy by adding them to regular "dependencies" of the project, along with the range. It can either satisfy or not satisfy the "semver range" you require in your plugin, and the user will be notified of the latter.

Semver ranges explained by npm: https://docs.npmjs.com/misc/semver
When in doubt always check: http://jubianchi.github.io/semver-check/

@MFry
Copy link

@MFry MFry commented Jul 10, 2017

@nikolakanacki to be able to easily install packages peerdependencies would be great!

@alexilyaev
Copy link

@alexilyaev alexilyaev commented Jul 22, 2017

@nikolakanacki Ok, so indeed when the end-user installs the package, devDependencies do not get installed, so a package author should add peerDependencies to devDependencies as well.

So, this solves the local development issue.

But, it seems that a lot of projects didn't add the peer dependency as a dev dependency.
So I guess we should start spreading the word and get projects on board.
This will inevitably lead to long discussions on why it worked with npm but not with Yarn, and regardless of the results, it's going to take a while and not all projects might do the change.

So... I'm proposing to still support a way to install peer dependencies, at least so we won't have to use install-peerdeps anymore.

@oliverjanik
Copy link

@oliverjanik oliverjanik commented Jul 23, 2017

What's the actual issue here? It does not seem installing one list of deps would be more complicated than installing another list of deps. Peer dependencies have been around for some years. How has this not bothered anyone?

@dwasyluk
Copy link

@dwasyluk dwasyluk commented Aug 11, 2017

@nikolakanacki solution makes perfect sense. It's what we're using for our library development. You need devDependencies setup properly in the library for isolated testing (outside of a host project that supplies the needed peerDependencies) and you need peerDependencies for integrated testing and to ensure the host project doesn't end up with redundant/duplicated package installations because the libraries it consumes are using the same dependencies and not making proper use of peerDependencies and devDependencies.

There is the small headache of keepin them in sync. But as @nikolakanacki pointed out this could easily be mitigated through some post-install scripting.

@ChrisBrownie55
Copy link

@ChrisBrownie55 ChrisBrownie55 commented Apr 14, 2019

I would definitely like to see this feature added. Without adding react to my package's devDependencies, I'm unable to run tests on my code.

A flag for installing the packages in the local peerDependencies object would be nice but I also don't see any downside to making installing only local peerDependencies the default behavior. And semantically it makes sense, the peer dependencies need to be there for the package to work everywhere else, why would it be any different locally?

My opinion on the usage for a flag would be the following because of its alignment with the
yarn add --peer command.

yarn --peer
# and
yarn install --peer

At the very least the flag should be introduced.

donaldshen added a commit to donaldshen/el-data-tree that referenced this issue Apr 29, 2019
将peerDependencies也加入到devDependencies中。
FYI: yarnpkg/yarn#1503
@jamstooks
Copy link

@jamstooks jamstooks commented Aug 15, 2019

I wonder if using separate test app is a good solution here? You could then add all your peerDependencies as dependencies of the test app. This seems to do the following:

  • keeps peerDependencies out of devDependencies in your library
  • you will be e2e testing your library, in a way... ensuring that your dist is built properly, you're exporting all your components correctly and that sort of thing
  • avoids the occasional Invalid hook call error when you forget to clear out node_modules from your package when using local dependencies, like "my-package": "file:/path/to/my-package"

If more info would be helpful for folks, I created a demo repo in an effort to model this approach and document the issue:
https://github.com/jamstooks/package-peer-dependencies

@flowirtz
Copy link

@flowirtz flowirtz commented Aug 18, 2019

For now, you should be able to run npx install-peerdeps <package> and the CLI then asks you whether you want to use Yarn for installing, if you have a yarn lock etc. in the folder. At least that worked for me just now.

@karlhorky
Copy link

@karlhorky karlhorky commented Oct 25, 2019

More discussion from Arcanis ("fail the install on missing peer deps") and Isaac ("install peer deps automatically") over here in this NPM RFC:

npm/rfcs#43

@willian
Copy link

@willian willian commented Oct 30, 2019

@emirotin
Copy link

@emirotin emirotin commented Mar 4, 2020

I have a related issue I think.
For the minimal repro I have this list of dependencies:

  "dependencies": {
    "prismic-reactjs": "^1.2.0"
  },
  "peerDependencies": {
    "react": "^16.12.0"
  },
  "devDependencies": {
    "react": "^16.12.0",
    "redux": "^4.0.5"
  }

Explanation: my package relies on react presence at runtime and also needs it for testing. redux is here for demo purposes, see below.

Now, prismic-reactjs also relies on react as its peer dependency.
What happens after yarn --production is called?

React is both installed and hoisted
I would expect none of the two to happen.

For the demo purposes redux is added here which is not installed which (I think) proves the transient peer dependency is the cause of the issue.

Repro repo: https://github.com/emirotin/yarn-react-repro. Run test.sh for the quick check.

vially added a commit to vially/backoff-rxjs that referenced this issue Mar 17, 2020
This is needed in development because yarn doesn't install
peerDependencies by default.

Yarn issue: yarnpkg/yarn#1503
@sajadghawami
Copy link

@sajadghawami sajadghawami commented Oct 25, 2020

npm has this feature now with v7... any reason not add this to yarn?

@karlhorky
Copy link

@karlhorky karlhorky commented Oct 26, 2020

@sajadghawami as far as I know, @arcanis has some pretty big reservations about doing this:

npm/rfcs#43 (comment)

@Vinchens00
Copy link

@Vinchens00 Vinchens00 commented Nov 19, 2020

Hi guys! I'm using yarn to develop library which is using peerDeps, so let me add my 5 cents on this topic.

I have some UI dependencies (react, react-dom, styled-component, etc) in peerDependecies. I can't add them to devDeps, because it'll cause some issues (for example, web app which will use my library, can't have 2 instances of react / styled-component when versions mismatch). So it makes sense to me to use peerDeps here.

But it make a lot of pain for me, because I have storybook and I need react / react-dom to render it and develop components of my library. To solve this right now I need to:

  1. Open package.json
  2. Copy versions of react / react-dom / etc
  3. Manually start yarn add --peer react@version react-dom@version. It's annoying, because I have to copy 4 libraries with version each time I'd like to make a clean install of node_modules (for any reasons).
    It also will be inconvenient in CI, when I'd like to build storybook as a static html and hosted at as documentation (storybook requires react).

Please, correct me if I'm missing something, but is there any way to make this automatically?

I was looking something like "yarn install --with-peers", but didn't find something except some third-party libraries.

@MrBr
Copy link

@MrBr MrBr commented Dec 26, 2020

Another way to go is to use typescript and @types packages.

By installing @types package (as deve dependency) of your peer dependencies you should be able to work.

Edit This goes only for compiler and IDE. It should stop those from complaining.

@Vinchens00
Copy link

@Vinchens00 Vinchens00 commented Dec 29, 2020

By installing @types package (as deve dependency) of your peer dependencies you should be able to work.

Hi! It doesn't work for my case, because I need react itself to run tests and build / run storybook.
I tried to add react as peer dep (to check on install) and as dev dep (to have react for my dev purposes) at the same time, but it looks like yarn doesn't support this scenario too.

@MrBr
Copy link

@MrBr MrBr commented Dec 29, 2020

You are right, I've updated my comment.

The point is that you should have playground package/folder for those kind of things. Playground package is used just for hosting libraries. It should provide environment in which you can test or develop you library. That package has all dependencies you need as devDependecies so you can work normaly.

If you work with monorepo it should be simple to do it and use your lib as a local dependency.

Emotionjs is a great example for this case https://github.com/emotion-js/emotion

@Vinchens00
Copy link

@Vinchens00 Vinchens00 commented Dec 29, 2020

It makes sense, but this approach still has some limitations. For example, your project should have another "playground repo" (in monorepo or independent repo - it's just a technical details).

I pretty sure it works, but it still looks like a workaround for me.

For example, I'm developing the library. I would like to test (jest) and document (storybook) without any additional repos, because I would like to have smooth automated CI from commit to production (npm registry with new version). So, my library should be able to test it itself.
I also use storybook during development, for example, to debug some stuff, so it's not really inconvenient to me link my library to another playground project to be able to debug it)

I'm okay to have react in peer and dev deps at the same time (because it looks like react should be checked like peer on install and needed during development to me). But this is also not supported.

I found https://github.com/christopherthielen/check-peer-dependencies for now, but I didn't implement needed behavior yet. I'd like yarn to install peer deps on local install and doesn't install them when my lib is used like dependency for another project. Playing with npm scripts right now.

@cayuu
Copy link

@cayuu cayuu commented Jan 3, 2021

Adding a reference point in case it helps broaden the context: our use-case is a (large commercial) project that deploys via container environments that do a yarn install --prod as part of creating the build images, and we have 3 very distinct dependency types:

  1. App dependencies: traditional core application dependencies. Needed to deploy.
  2. Pure development env dependencies: linters, types, analysers, dev servers and runners, etc. devDependencies. NOT needed to deploy.
  3. Build dependencies: everything required to build our app (typescript, webpack, plugins, etc). Ideally peerDependencies (in our context "peer" would mean "needed in the environment"). Needed to deploy.

For download+build speed, we originally chose an explicit yarn install --prod when deploying because there was/is no way to ONLY install dependencies (--prod) and peerDependencies (--peer). Which meant we had to choose between stuffing 20+ "build" dependencies into dependencies (which is what we did) OR sticking the build deps wherever and firing off a yarn install to download all of the things, dealing with the extra download (and worst of all: build times) of dozens of irrelevant devDependencies. The cost of our chosen approach is additional cognitive overhead trying to parse our "app" dependencies.

At the project's large size and heavy complexity now, we're considering making the call to pay that cost in slower builds. But it's a horrible trade-off. So is adding "yet another dependency" to manage our dependency installation because our package manager doesn't stretch that far. So we try to choose the lesser of the evils, but that's a moving target as the project evolves.

The ideal would be any of the following (which would allow us to separate 'build requirements' into a separate stack of dependencies):

  1. yarn install --prod --peer
  2. yarn install --prod --optional
  3. or yarn install --ignore-devDepedencies
@merceyz
Copy link
Member

@merceyz merceyz commented Jan 3, 2021

Closing as fixed in v2 where you can make a small plugin to install a subset of your dependencies (cherry picking build dependencies out of devDependencies for example).

As an example the focus command in v2 which handles the --production installs as well as others is ~100 lines https://github.com/yarnpkg/berry/blob/b0ad235f1d7d13ba5d92682e55407ee91750442e/packages/plugin-workspace-tools/sources/commands/focus.ts

https://yarnpkg.com/getting-started/migration

@merceyz merceyz closed this Jan 3, 2021
badeball added a commit to badeball/cypress-cucumber-preprocessor that referenced this issue Apr 29, 2021
A more thorough discussion can be found here [1].

[1] yarnpkg/yarn#1503
badeball added a commit to badeball/cypress-cucumber-preprocessor that referenced this issue Apr 29, 2021
A more thorough discussion can be found here [1].

[1] yarnpkg/yarn#1503
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.