-
Notifications
You must be signed in to change notification settings - Fork 2
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
Scoped approach to packages’ dependencies graph #4
Comments
It took some time but I finally found evidence of this case in the wild without the need to resort to edge cases for example. Take a look at the current compatibility matrix of "version": "5.0.1",
// ...
"peerDependencies": {
"react": "^0.14.0 || ^15.0.0-0",
"redux": "^2.0.0 || ^3.0.0"
} This means that the current superflat approach would make thins hairy to debug in this normal case (full dependency graph shown here):
While A possible solution is to fully qualify packages with
|
Hey @yuchi, we're actually looking to see if we can switch from |
The main way We could have the same approach, either
In case (1) we will encounter collisions and side effects. Read «installing a bundle is not safe». There’s another way we could benefit from forcing |
Let me make it even clearer, since I personally believe this is the biggest stopper here and must be well understood by everyone on board. If I have two bundles which requires different versions of const reactRedux = require('react-redux');
const React = require('react');
const Component = React.Component;
// This throws
console.assert(reactRedux.connect( …… )( …… ) instanceof Component); |
You can now have fun with a toy implementation of a resolution algorithm which supports the expected Just clone, As you’ll see having as a peer-dependency a package which has peerDependencies doesn’t work. |
I updated that Proof of Concept a lot:
Please have a look and let me know if something is not clear. |
Hi @yuchi, Thanks for the update. I'm currently viewing the changes and will let you know if I have any questions. |
There’s one main design issue with the current implementation.
Packages are aggressively deduped, way beyond of what npm v3 does, and it’s less predictable than yarn forcefully flat dependencies layout.
Let me show an example.
Given the existence of these fake packages versions and their dependencies:
angular
^1.0.0
, that depends onincremental-dom
^2.0.0
metal
^3.0.0
, that depends onincremental-dom
^2.0.0
incremental-dom
^4.0.0
In npm v3 we’d expect a layout that gives different instances for metal and angular:
In yarn with
--flat
we’d expect a single version available to the whole project:Neither are the case now. Since we have a flat registry of versioned packages it is pretty trivial for us to bind every package to the highest version available for a dependency. This is pretty cool: every package has access to what it needs, yet we dedupe as much as we can.
The problem is that if angular does something nasty to incremental-dom (such as tampering some prototype or installing some plugin) that means that the tampered version is offered to metal too. This is not inherently bad, simply different from the expected behaviour and could be the cause of bugs and issues incredibly difficult to understand.
To be completely honest I believe a similar issues exists with npm.
Here’s an example:
extract-cat-names
^1.0.0
, that depends onunderscore
^1.0.0
underscore.strings
^1.0.0
calculate-alien-age
^1.0.0
, that depends onunderscore
^1.0.0
underscore.strings
^2.0.0
In npm v3 we get this:
Which one gets moved to the root depends simply on the alphabetical order.
But if
underscore.string
is used as such:That means that which one ends being called is the last one in the execution order (
_.mixin
adds methods to_
) and for sure one between calculate-alien-age and extract-cat-names will get the wrong version.The text was updated successfully, but these errors were encountered: