Recently, we encountered some bower packages version conflicts issues. I believe the story is that we installed a new package called angular-touch. We installed it locally on our dev environment using the following command:
bower install angular-touch –save
The –save will add the package to the bower.json file. However, for some reason, we did not get a warning about that it needs a newer version of angular (1.4.3) than what we had (1.3.6). It may just silently updated it. Only when we committed the change and the build machine start to build from scratch, the issue showed up and we got his error:
Unable to find a suitable version for angular, please choose one:
1) angular#>=1 <1.3.0 which resolved to 1.2.28 and is required by angular-bootstrap#0.12.0
2) angular#1.2.28 which resolved to 1.2.28 and is required by angular-loader#1.2.28
3) angular#1.3.12 which resolved to 1.3.12 and is required by angular-resource#1.3.12
4) angular#1.3.16 which resolved to 1.3.16 and is required by angular-mocks#1.3.16, eMenu-web
5) angular#>= 1.0.8 which resolved to 1.3.16 and is required by angular-ui-router#0.2.10
6) angular#>=1.2.10 which resolved to 1.3.16 and is required by angular-carousel#0.3.12
7) angular#>=1.0.8 which resolved to 1.3.16 and is required by ngGeolocation#0.0.7
8) angular#~1.x which resolved to 1.3.16 and is required by angular-spinner#0.6.2
9) angular#>= 1.2.23 which resolved to 1.3.16 and is required by ngCordova#0.1.15-alpha
10) angular#1.4.3 which resolved to 1.4.3 and is required by angular-touch#1.4.3Prefix the choice with ! to persist it to bower.json
Here is something I really don’t like (that’s probably also why I’m writing a blog about it): Bower, like a lot other package management systems (npm, pip, maven, etc) allows you to specify version ranges. In this example, you can see notations “>=”, “<“, “~1.x” etc. Personally, I like all the things to be fixed. My thought is that deterministic is way better than random. That is probably why I like docker a lot.
I understand why they did this though. Because when your project depends on multiple libraries (let’s say A and B), they may in turn all depends on another library (let’s say C). If A want v1.1 of C and B want v1.2 of C, you got a conflict when A may work with anything greater than v1.1. So, to make it easy, they allow library writers to specify version range and must have some smart logic to pick one of the many versions that satisfies all the requirements (or just pick the latest that satisfies). It is only when they really cannot find anything to satisfies it, they ask a human like above. However in our case, it is too late because it is the build machine installing the packages.
Now, maybe it will be very annoying if we do not have version range and developers have to manually resolve conflicts a lot. Personally I feel much better knowing what exactly is my program using but others may not care and just want to use some library easily. Then I would ask this question: why don’t we have a platform can hold multiple versions of same package and let others use whatever version they need? Maybe it is very hard and need support from the programming language level. But in my opinion, it will be awesome. We will be able to encapsulate a lot better. Yes, the final size of your program may be several times depends on average how many versions of packages you included, but disk space and memory are getting much cheaper these days.