yarnpkg / yarn

The 1.x line is frozen - features and bugfixes now happen on https://github.com/yarnpkg/berry
https://classic.yarnpkg.com
Other
41.44k stars 2.73k forks source link

Install multiple versions of a dependency #1508

Open graingert opened 8 years ago

graingert commented 8 years ago

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

What is the current behaviour? Versions can be nested or flat with no solution.

If the current behaviour is a bug, please provide the steps to reproduce. N/A

What is the expected behaviour?

Please mention your node.js, yarn and operating system version.

Currently a package can have only a single version of a dependency defined. I have a need to install multiple versions of a dependency at once.

In my use case I have a library (frozen-express) that can during runtime take an object produced by another library (Express app) and do useful things with it. I support multiple versions of Express.

During development I want to be able to test my application with different versions of my dependency. I could fake both versions of Express, but I consider that using a real Express app is a better deal. The tests become more of integration tests as opposed to unit tests, but that only makes them more useful.

I could use npm install express@3 && npm test && npm install express@4 && npm test, but that is very significantly slower than running my entire test suite. In addition, this wrecks any chance of receiving proper code coverage reports. Obviously, I have code that conditionally applies to one or another version, and no code coverage tool understands that, if I need to run npm test twice (or more times).

The best workaround is, unfortunately, abusing the npm database. A single-line module express3 that depends on express@3 and exports it solves all my problems.

Perhaps this is something Yarn could do that npm won't: https://github.com/npm/npm/issues/5499

mnpenner commented 7 years ago

The best workaround is, unfortunately, abusing the npm database. A single-line module express3 that depends on express@3 and exports it solves all my problems.

This works fine when you only want to import from the "main" file, but it becomes really ugly when you want to import a specific file. Here's what I have to do right now with npm because I need both lodash@3 and lodash@4:

const setIn = require('lodash4/node_modules/lodash/fp/set');
const getOr = require('lodash4/node_modules/lodash/fp/getOr');
const toPath = require('lodash4/node_modules/lodash/toPath');
graingert commented 7 years ago

And doesn't work with flat mode

wclr commented 7 years ago

The best workaround is, unfortunately, abusing the npm database

I believe the better workaround would be to create a separate folder with needed dependency version in package.json and add it as file file: dependency to the project (using custom name needed), I believe it should work.

graingert commented 7 years ago

@whitecolor does that work with flat mode?

wclr commented 7 years ago

What you mean by "work"? This will install dependency in nested node_modules.

you may do in index.js file:

exports = require('express')

It will expose its nested express

mnpenner commented 7 years ago

@whitecolor Will yarn recursively install dependencies from nested package.json files?

wclr commented 7 years ago

Will yarn recursively install dependencies from nested package.json files?

from what nested package.json? if your say add my-express: file:... module dependency to your /project/package.json and this module will contain only express dependency (that is not compatible with express that resides in /project/node_modules) it will install this express in /project/node_modules/my-express/node_modules/express and all express dependencies will go to /project/node_modules/my-express/node_modules.

mnpenner commented 7 years ago

@whitecolor Sorry, can you spell it out? I can't seem to get it to work the way you describe.

Here's a gist of what I tried: https://gist.github.com/mnpenner/c46a5eff34cfa91f361a8b3baa249a10

When I run yarn in the root project directory it says:

❯ yarn
yarn install v0.27.5
warning package.json: No license field
warning No license field
[1/4] Resolving packages...
error Package "express3@" doesn't have a "version".
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.

i.e., not only does it not install the sub-dependency, but it errors out because it can't determine the version.

wclr commented 7 years ago

You need to define name and version fields in express3/package.json, npm/yarn use name field to determine where to install this package in node_modules.

mnpenner commented 7 years ago

@whitecolor Got it. I see how that works now. Thank you!

It's a bit tedious, but I think it's the best solution we have right now.

egmanoj commented 7 years ago

@mnpenner Can you update the gist with the changes you made? Thanks.

mnpenner commented 7 years ago

@egmanoj Sure. Updated. The name should probably be something that won't collide with something already on npmjs.org -- you might be able to namespace it with @localpkg/ or something like that if you want. I don't think the version matters at all. Just choose a stable number like 1.0.0 or you can use the version of the package if you want.

mnpenner commented 7 years ago

I haven't tried it yet, but apparently this feature already exists.

egmanoj commented 7 years ago

@mnpenner Tried it, worked quite well.

Caveat: Aliases do not work with installed TypeScript type definitions (Please correct me if I'm wrong). I.e. if you have both package and (aliased) package-latest, and want to use the @types type definitions for both package and package-latest, you are out of luck.

wclr commented 7 years ago

and want to use the @types type definitions for both package and package-latest, you are out of luck.

I tried to install yarn add @type/package@types/package-latest but it fails it seems that this method doesn't support scoped packages, so I believe it is a bug and an issue should be created, if not exists.