10 ms·
Multiple versions may sound like it's useful, but it's almost always a bad idea. Cargo doesn't allow it either. The problem isn't really fundamental. Bundler m
by lucian1900 10y ago
Multiple versions may sound like it's useful, but it's almost always a bad idea. Cargo doesn't allow it either.
The problem isn't really fundamental. Bundler makes almost all the right choices already. Its major disadvantage is that it only works for Ruby.
- dikaiosune 10y agoCargo definitely allows two dependencies to rely on different versions of a transitive dependency. If those deps expose a type from that dependency in their API, you can very occasionally get weird type errors because the "same" type comes from two different libraries. But otherwise it Just Works(tm).
- steveklabnik 10y agoCargo does allow multiple versions of transitive dependencies. It tries to unify them as much as possible, but if it can't, it will bring in two different versions. What it _won't_ let you do is pass a v1.0 type to something that requires a v2.0 type. This will result in a compilation error. There's been some discussion around increasing Cargo's capacity in this regard (being able to say that a dependency is purely internal vs not), we'll see.
- Siyo 10y agoI feel like this is especially problematic when using NPM for your frontend. Now you have to run all your code through deduplication and slow down your build times or end up with huge assets. I wonder if it's really worth the trouble.
- rictic 10y agoThis is especially true when you're going to be serving your code over the web. It's very easy when using npm to accidentally end up shipping a lot of duplicate code. That alone has me super excited about Yarn, before even getting into the performance, security, and 'no invisible dependency' wins.
- wycats 10y agoAs a practical matter, the npm ecosystem today relies on duplication, and no new client that made the "highlander rule" (there can be only one) mandatory could succeed. Yarn does offer a `--flat` option that enforces the highlander rule, and I'm hopeful that the existence of this option will nudge the ecosystem towards an appreciation for fewer semver-major bumps and more ecosystem-wide effort to enable whole apps to work with `--flat` mode. Plz send halp!
- smrtinsert 10y agoExplain why duplication is mandatory?
- hbhakhra 10y agoJust imagine two packages you depend on (a and b) that both have a shared dependency (x). Both start off depending on x version 1.0 but then later a is updated to 2.0 while b isn't. Now you have two packages depending on different versions of the same package and hence the need for duplication. You have a that needs x@2.0 and b that needs x@1.0, so both copies are kept.
- prodigal_erik 10y agoDon't upgrade a when it wants a half-baked x. Choose versions of a and b that agree on a known-good version of x. If there aren't any, it's not sane to use a and b together unless x is written very carefully to accommodate data from past and future versions of itself.
- gakada 10y agoThat's not how it works. There will be two copies of x in the require cache. They don't know of each other's existence.
- prodigal_erik 10y agoI'm arguing for choosing dependency versions that don't require you to break the highlander rule. "a is updated to 2.0" doesn't mean you should start using that version of a right now.
- thejameskyle 10y agoYarn supports `yarn [install/add] --flat` for resolving dependencies to a single version
- lf-non 10y agoWith tiny modular utilities this is very much necessity - and not a bad idea if the different versions are being used in different contexts. For instance, when using gemified javascript libraries with bundler it is painful to upgrade to a different version of a javascript library for the user facing site while letting the backend admin interface continue using an older one for compatibility with other dependencies.
- _greim_ 10y ago> Multiple versions [...] almost always a bad idea If so, different major versions of the same dep should be considered different libraries, for the sake of flattening. Consider lodash for example.
- wycats 10y agoThat's exactly what Cargo does, but it also takes a further step of making `^` the default operator and strongly discouraging version ranges other than "semver compatible" post-1.0.
- Ajedi32 10y agoLooks like Yarn does something similar: https://yarnpkg.com/en/docs/cli/add#toc-yarn-add-exact https://yarnpkg.com/en/docs/cli/add#toc-yarn-add-exact Personally I'm not really sure I like it. If I specify an exact revision of something, chances are I really do mean to install that exact revision. I don't see why I need an extra flag for that.
- fryguy 10y agoThat can cause some serious problems in at least some portion of times. I've dealt with the subtle errors that have been caused by this problem in c++, and don't really know javascript libraries that well so I can't give a more concrete example. But imagine that there are the following libraries: * LA: handles linear algebra and defines a matrix object. * A: reads in a csv file and generates a matrix object using LA * B: takes in a matrix object from LA, and does some operations on it In this case, if B depends on version 5 of LA and the new version of A depends on version 6 of LA, then there's going to be a problem passing an object that A generated from version 6 and passing it to B which depends on version 5.
- spion 10y agoThe problem does happen in JavaScript. But since its unityped, there is a strategy to deal with it * Figure out early on (before 1.0) what your base interface will be. For example, for a promise library, that would be `then` as specified by Promises/A+ * Check if the argument is an instance of the exact same version. This works well enough if you use `instanceof`, since classes defined in a different copy of the module will have their own class value - a different unique object. * If instanceof returns true, use the fast path code (no conversion) * Otherwise, perform a conversion (e.g. "thenable" assimilation) that only relies on the base interface Its not easy, but its not always necessary either. Most JS libraries don't need to interoperate with objects from previous versions of themselves.
- twhb 10y agoYou've got to take the ecosystem into account. There are a lot of very depended-upon modules that are 1 KB of code and bump their major version as a morning habit. Forcing people to reconcile all 8 ways they indirectly depend on the module would drive them nuts, but including 4 copies of the module doesn't hurt much.