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 · 84 comments
Closed
Labels
cat-feature fixed-in-modern This issue has been fixed / implemented in Yarn 2+. help wanted triaged

Comments

@jshthornton
Copy link

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

@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 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

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

Apparently not important to NPM devs.

@gf3
Copy link

gf3 commented Jan 30, 2017

+1 this is important for library authors

@nathanhleung
Copy link

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

@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 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

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

@avegancafe
Copy link

@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

@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

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

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

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.

@avegancafe
Copy link

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 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

@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

@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 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

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 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

@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 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 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 commented Jul 10, 2017

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

@alexilyaev
Copy link

@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

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 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.

@sajadghawami
Copy link

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

@karlhorky
Copy link

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

npm/rfcs#43 (comment)

@Vinchens00
Copy link

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 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

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 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

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 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 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 as completed Jan 3, 2021
@merceyz merceyz added the fixed-in-modern This issue has been fixed / implemented in Yarn 2+. label Jan 3, 2021
badeball added a commit to badeball/cypress-cucumber-preprocessor-deprecated that referenced this issue Apr 29, 2021
A more thorough discussion can be found here [1].

[1] yarnpkg/yarn#1503
@emahuni
Copy link

emahuni commented Oct 23, 2021

Why can't yarn just implement auto-peer dependencies installation just like how npm 7 has done? It's much easier and cleaner IMO. I don't want to jump ship, again, but this takes development time just to do something that the other package manager can do out of the box.

I believe yarn can do this better than npm.

@villesau
Copy link

villesau commented Jun 10, 2022

@merceyz I think the issue should be reopened. As seen from the reactions, the solution proposed is largely considered suboptimal. npm is indeed way ahead with this. There is a lot of cumulative development time spent dealing with peer dependencies that yarn could easily handle automatically.

@dvkellerman

This comment was marked as abuse.

@fabis94
Copy link

fabis94 commented Oct 14, 2022

Yea, I agree that you shouldn't need to write a plugin to do this, it's a fairly common use case...

@felicandalc

This comment was marked as abuse.

@yarnpkg yarnpkg locked as resolved and limited conversation to collaborators Oct 20, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cat-feature fixed-in-modern This issue has been fixed / implemented in Yarn 2+. help wanted triaged
Projects
None yet
Development

Successfully merging a pull request may close this issue.