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

TODO: what's a real-world example of dependency hell? #5

Closed
domenic opened this issue Mar 15, 2018 · 8 comments
Closed

TODO: what's a real-world example of dependency hell? #5

domenic opened this issue Mar 15, 2018 · 8 comments

Comments

@domenic
Copy link
Collaborator

domenic commented Mar 15, 2018

Preferably:

  • Using packages that exist on npm
  • Using packages that would be used on the frontend
  • Not involving lodash, since we use that as our example of a package's name (lodash-es) and its specifier (lodash) not matching
  • Non-dev dependencies

This would replace our current fake example.

@justinfagnani
Copy link
Collaborator

I've definitely hit this in my projects with lodash 3 and 4, and not lodash-es.

Some similarly low-level common library like underscore, rxjs, etc. would probably yield examples.

@Jessidhia
Copy link

react-popper, which still requires react 15 because it accesses import React from 'react'; React.PropTypes, but that has been removed in react 16.

Though I guess react+react-dom is an example of the opposite problem; everything you load must use the exact same packages, as loading more than one will cause conflicts even if they're the exact same version; the bloat is the least of the problems.

I currently work around it by doing a string replace in the source code to import PropTypes from 'prop-types' instead, but an alternative could be to have a package map just for that module that would export { default } from 'react'; export { default as PropTypes } from 'prop-types'.

Note how, as this module would be providing react itself for react-popper, it still needs to be able to import the real react by name, so the mapping would have to not apply for the shim package.

@domenic

This comment has been minimized.

@zkat
Copy link

zkat commented Mar 19, 2018

So, I have this internal webapp I often run npm-related tests in because it's been such a good example of modern "real world" webapps. It doesn't take long to find potential conflicts using npm ls that could affect frontend deps:

Two different versions of regenerator-runtime in a single tree
├─┬ babel-core@6.26.0
│ └─┬ babel-runtime@6.26.0
│   └── regenerator-runtime@0.11.0  deduped
├─┬ babili@0.0.12
│ └─┬ babel-cli@6.26.0
│   └─┬ babel-polyfill@6.26.0
│     └── regenerator-runtime@0.10.5 
├── regenerator-runtime@0.11.0 
└─┬ tap@10.7.2
  └─┬ nyc@11.2.1
    └─┬ istanbul-lib-instrument@1.8.0
      └─┬ babel-generator@6.26.0
        └─┬ babel-runtime@6.26.0
          └── regenerator-runtime@0.11.0 

Two different semver-major versions of querystringify used by sockjs-client
  └─┬ sockjs-client@1.1.4
    ├─┬ eventsource@0.1.6
    │ └─┬ original@1.0.0
    │   └─┬ url-parse@1.0.5
    │     └── querystringify@0.0.4 
    └─┬ url-parse@1.2.0
      └── querystringify@1.0.0

With your forgiveness, I'm also going to share some non-lodash examples that show up in server-side/tooling deps which I think would just as reasonably be used on the frontend. I think it's important to note that a big reason why there might not be as many real-world multiversion examples that involve actual conflicts is because so many folks are restricted by the dependency-hellish world that frontend exists in right now that there's a bit of a cultural thing against even letting it get to this point. The Node.js world, by contrast, has been much more aggressive about small-modules, and thus a potential increase in version conflicts, because the Node algorithm has always protected them from that.

Tree showing multiple locations of har-validator at 3 different versions.
├─┬ [redacted]@10.0.7
│ ├─┬ chokidar@1.7.0
│ │ └─┬ fsevents@1.1.3
│ │   └─┬ node-pre-gyp@0.6.39
│ │     └─┬ request@2.81.0
│ │       └── har-validator@4.2.1 
│ └─┬ numbat-emitter@4.0.1
│   └─┬ request@2.81.0
│     └── har-validator@4.2.1  deduped
├─┬ etcdjs@2.4.2
│ └─┬ request@2.81.0
│   └── har-validator@4.2.1 
├─┬ node-zendesk@1.2.0
│ └─┬ request@2.74.0
│   └── har-validator@2.0.6 
├─┬ nodesi@1.6.4
│ └─┬ good-guy-http@1.10.2
│   └─┬ request@2.81.0
│     └── har-validator@4.2.1  deduped
├─┬ request@2.83.0
│ └── har-validator@5.0.3 
└─┬ tap@10.7.2
  └─┬ coveralls@2.13.3
    └─┬ request@2.79.0
      └── har-validator@2.0.6 

Another example from the same app involves 4 different semver-major versions of the same library:

Another npm ls showing camelcase at versions 1, 2, 3, and 4.
├─┬ @npm/readme-client@1.4.2
│ └─┬ yargs@6.6.0
│   ├── camelcase@3.0.0 
│   └─┬ yargs-parser@4.2.1
│     └── camelcase@3.0.0  deduped
├─┬ @npm/spife@10.0.7
│ └─┬ tacks@1.2.6
│   └─┬ yargs@3.32.0
│     └── camelcase@2.1.1  deduped
├─┬ @npmcorp/mkenv@1.5.1
│ └─┬ yargs@8.0.2
│   ├── camelcase@4.1.0 
│   └─┬ yargs-parser@7.0.0
│     └── camelcase@4.1.0  deduped
├─┬ etcetera@2.2.0
│ ├─┬ update-notifier@2.2.0
│ │ └─┬ boxen@1.2.1
│ │   └── camelcase@4.1.0 
│ └─┬ yargs@8.0.2
│   ├── camelcase@4.1.0 
│   └─┬ yargs-parser@7.0.0
│     └── camelcase@4.1.0  deduped
├─┬ gravatar@1.6.0
│ └─┬ yargs@6.6.0
│   ├── camelcase@3.0.0 
│   └─┬ yargs-parser@4.2.1
│     └── camelcase@3.0.0  deduped
├─┬ jest@20.0.4
│ └─┬ jest-cli@20.0.4
│   ├─┬ jest-runtime@20.0.4
│   │ └─┬ yargs@7.1.0
│   │   ├── camelcase@3.0.0 
│   │   └─┬ yargs-parser@5.0.0
│   │     └── camelcase@3.0.0  deduped
│   └─┬ yargs@7.1.0
│     ├── camelcase@3.0.0 
│     └─┬ yargs-parser@5.0.0
│       └── camelcase@3.0.0  deduped
├─┬ node-zendesk@1.2.0
│ └─┬ nconf@0.7.2
│   └─┬ yargs@3.15.0
│     └── camelcase@1.2.1 
├─┬ nunjucks@3.0.1
│ └─┬ yargs@3.32.0
│   └── camelcase@2.1.1 
├─┬ qrcode@1.0.0
│ └─┬ yargs@8.0.2
│   ├── camelcase@4.1.0 
│   └─┬ yargs-parser@7.0.0
│     └── camelcase@4.1.0  deduped
├─┬ tap@10.7.2
│ └─┬ nyc@11.2.1
│   ├─┬ istanbul-reports@1.1.2
│   │ └─┬ handlebars@4.0.10
│   │   └─┬ uglify-js@2.8.29
│   │     └─┬ yargs@3.10.0
│   │       └── camelcase@1.2.1 
│   ├─┬ yargs@8.0.2
│   │ ├── camelcase@4.1.0 
│   │ └─┬ yargs-parser@7.0.0
│   │   └── camelcase@4.1.0  deduped
│   └─┬ yargs-parser@5.0.0
│     └── camelcase@3.0.0 
├─┬ webpack@3.7.1
│ ├─┬ uglifyjs-webpack-plugin@0.4.6
│ │ └─┬ uglify-js@2.8.29
│ │   └─┬ yargs@3.10.0
│ │     └── camelcase@1.2.1 
│ └─┬ yargs@8.0.2
│   ├── camelcase@4.1.0 
│   └─┬ yargs-parser@7.0.0
│     └── camelcase@4.1.0  deduped
└─┬ yargs@10.1.1
  └─┬ yargs-parser@8.1.0
    └── camelcase@4.1.0 

@justinfagnani
Copy link
Collaborator

Hey @zkat thanks! Can you put the last three example in code blocks? :)

@Jessidhia
Copy link

It seems they are in code blocks but the formatting is being crazy. GitHub also isn't correctly expanding the second <details>.

@zkat
Copy link

zkat commented Mar 20, 2018

Sorry about that! Fixed!

@domenic
Copy link
Collaborator Author

domenic commented Nov 2, 2018

This has been incorporated into the overhauled proposal! https://github.com/domenic/import-maps#multiple-versions-of-the-same-module

@domenic domenic closed this as completed Nov 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants