webpack/webpack

Start warning when multiple versions of a library appear in one build

alanhogan opened this issue · 17 comments

clayallsopp/react.backbone#26 and similar issues would be more readily identified and prevented if Webpack could say things like “hey, just FYI, you have <React/Underscore/jQuery> being included twice in this build.” Will be a common problem as the industry moves away from a manual folder of lib/some-library.min.js towards package.json and various dependency management tools.

I think it's a common problem for NPM on client-side and, while Webpack plugin could do this, I think it would benefit a wider community if we could mark packages we want to never be duped, in some way in package.json.

@domenic what do you think? You advocated NPM on client-side, this is a very typical issue.

I think it should warn if there are two copies that are the same major version. E.g. if you have 1.5.2 and 2.1.0 it should not warn, but if you have 2.0.1 and 2.1.0 it should warn. Also it should never warn on multiple 0.x.y versions. (So basically it should warn if you have two copies that are semver-compatible.)

The warning would then happen in only a few cases:

  • Cases like "^2.0.1" plus "^2.1.0", where you forgot to run npm dedupe, and running npm dedupe will fix it.
  • Cases like "2.0.x" plus "2.1.0", where the authors of those packages are being too strict; they should be using ^. In this case the warning tells you to go bug them.
  • Cases like Backbone 1.2 plus Backbone 1.6, where you need both because Backbone does not follow semver. In this case the warning is spurious.

That's a tricky issue, we discussed it a lot (#105 #47 #340). Imho npm dedupe is not usable as it changes the runtime behavior. Two modules, which had a separate instance of a module, will share a single instance after npm dedupe. This is a serious problem when modules provide a global config like myModule.someConfig = true. It's better to use webpack's DedupePlugin because it preserves runtime behavior.

@domenic has this issue been discussed at npm?

@alanhogan maybe warnings are a bit too strong. It would be nice if webpack provided optimizations hints on demand.

Thanks for your response. I’m glad to see this is under a lot of debate.

I don’t much care whether they are packaged as hints or warnings. But I will say that more than just an optimization, this can cause serious (and subtle) bugs; a warning may yet be appropriate.

This would be nice - I've spent days debugging why my router plugins were not working, and after I noticed that the backbone.js I was debugging was not the same file as the one I had installed I realized what was wrong.

I think this is a very important feature when using NPM and webpack, not only because of possible bugs but also to avoid bloating the build with different versions of the same package.

Update:
Written a small Webpack plugin to warn in such cases: https://github.com/darrenscerri/duplicate-package-checker-webpack-plugin

Webpack 2 dropped the DedepePlugin: https://webpack.js.org/guides/migrating/#dedupeplugin-has-been-removed.

Using the plugin provided by @darrenscerri, I can see that my build does have duplicates.

In development:

WARNING! Duplicate packages found.
<regenerator-runtime> - 0.10.1, 0.9.6

In production:

WARNING! Duplicate packages found.
<babel-runtime> - 6.22.0, 6.18.0
<fbjs> - 0.8.6, 0.1.0-alpha.7
<regenerator-runtime> - 0.10.1, 0.9.6
<component-emitter> - 1.2.1, 1.2.0

What is the recommended approach to handling duplicates without DedupePlugin?
I guess in my case I should just make sure I update some of my packages (switching to webpack 2 and haven't upgraded all dependencies yet). But is there a general guideline or recommendation?

@loopmode. You would need to start by checking which modules are requiring those duplicates. Usually the solution is to update your dependencies.

What do you do if they include third party dependencies from dependencies which were already updated to the latest version?
This is the output that I get in my case:
`
3.0.0 .//warning from .//react-router/es/routerWarning.js
2.1.0 .//react-widgets//warning from ./~/react-widgets/lib/ListGroupable.js

3.2.1 ./~/dom-helpers from ./~/react-bootstrap/lib/Modal.js 2.4.0 ./~/react-widgets/~/dom-helpers from ./~/react-widgets/~/dom-helpers/query/height.js

<lodash.debounce>
4.0.8 .//lodash.debounce from .//redux-devtools-log-monitor/lib/LogMonitor.js
3.1.1 .//react-dock//lodash.debounce from ./~/react-dock/lib/Dock.js
`

I'm wondering the same thing. After updating React (using yarn):

duplicate-package-checker:
  <fbjs>
    0.8.12 ./~/fbjs
    0.8.16 ./~/react-dom/~/fbjs

fbjs is not a dependency in my package.json, so I'm not sure how it ended up at ~/fbjs. What is the solution to resolving a duplication like this?

I think yarn now has an option that allows you to override package versions of your depencencies’ depencencies via a new option in package.json. They call this “selective version resolution.” I haven’t tried it yet.
yarnpkg/yarn#4105

Does exist some kind of approach to solve the problem that dg-grow-virgiliu-ratoi exposed?

I'll try it, thanks. :)

Anyway, is in the roadmap some kind of stable solution for this problem? npm allows multiple versions for any dependency, It's not difficult to reproduce this problem.

This issue had no activity for at least three months.

It's subject to automatic issue closing if there is no activity in the next 15 days.

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

9 years later let's work on this 🤣😭😅🙃