0 Comments

The Problem

Recently, at work, we ran into an issue where a particular package update (angular-bootstrap) broke one of our crucial features.  Apparently, as mentioned here: https://github.com/angular-ui/bootstrap/wiki/Migration-guide-for-prefixes, the newer version (since 0.14.0) requires the directive selector to be prefixed with “uib-“. 

Potential Solutions

So, there are some solutions / options here:

Option 1

Completely fall back to version 0.13.4 to avoid the prefixing.

Advantage: there is very little new code that depends on the newer version where everything is prefixed with “uib-“.  So there is really minimal rework to be done to fix this issue.

Disadvantage: This locks any new development on the same project to version 0.13.4 and if anything new added afterward, we will not be able to take advantage of that.

Option 2

Upgrade the crucial feature to the latest version (i.e. 1.3.3).

Advantage: If anything new implemented in the package, we can take advantage of it.   Latest and greatest, yes!

Disadvantage: You are basically on the upgrade train forever.  Tons of rework and retesting to make sure that legacy code is always working going forward.

Option 3

Somehow allow multiple version of the library to be used side-by-side

Advantage: No major rework need to be done on the crucial feature.  It can stay happy at version 0.13.4.  New custom components / features can be on a newer version of the library (i.e. 1.3.3).  Good isolation.

Disadvantage: Eh…. *thinking*… *more thinking*…. nothing… (Well this is not true, we will still need to retouch the crucial feature where we are importing this component since the alias will change in the require / import statements)

Option 3 is definitely the clear winner here, but the question is … HOW?

So, I’ve looked at the different package managers that come to mind, which are:

  1. NPM
  2. JSPM
  3. Webpack

Webpack

Well, let’s rule Webpack out since it’s not really a package manager.  I have to admit I’m not a Webpack user, but looking around the web, I found this article: http://ilikekillnerds.com/2015/07/jspm-vs-webpack/ which basically tell me straight out that basically, and I am quoting here, “It actually offers almost everything that Jspm does except it is not a package  manager”.  Then again this article is pretty old (in JavaScript timeframe, LOL), so things might have changed now.  If anyone know any different, let me know…

So that leaves me with only NPM and JSPM.

JSPM

Now, at work, we are already using JSPM, so this becomes the first choice for me to investigate.  And from my investigation (which is not much…), basically, I ran jspm help on the console and Ouila! I came across this line: install jquery=…     Hmm… that looks like aliasing to me, so I gave it a try.  Created a test folder, ran jspm init, and then ran jspm install angular-bootstrap0134=angular-bootstrap@0.13.4 and then again jspm install angular-bootstrap133=angular-bootstrap@1.3.3.  And… guess what?  It FREAKING works!!! YAY!!

In package.json I saw:

"jspm": {
  "dependencies": {
    "angular-bootsrap133": "github:angular-ui/bootstrap-bower@1.3.3",
    "angular-bootstrap0134": "github:angular-ui/bootstrap-bower@0.13.4",

Similarly, in system.js config file:

map: {
    "angular-bootsrap133": "github:angular-ui/bootstrap-bower@1.3.3",
    "angular-bootstrap0134": "github:angular-ui/bootstrap-bower@0.13.4",

Therefore, now where I need the older version I can just require(“angular-bootstrap133”) or in ES2015 syntax: import “angular-bootstrap133”

PERFECT! Problem solved.

So…

NPM

Just to be complete, I tried to figure out how to do this using plain vanilla NPM… 

I looked around on the web and I found this article which is pretty old and it looks a bit promising: http://blog.izs.me/post/1675072029/10-cool-things-you-probably-didnt-realize-npm, especially the big bold section titled 1:Handle multiple versions of the same thing at the same time.

Looked through npm help install documentation as well, but there is nothing there that tell me how to do this…

So, I tried by running npm install angular-ui-bootstrap@0.13.4 --save and that net me a node_module/angular_ui_bootstrap folder and the following lines in package.json:

"dependencies": {
   "angular-ui-bootstrap": "^0.13.4",

Then I tried again using npm install angular-ui-bootstrap@1.3.3 --save, and as expected, it basically override the node_module/angular_ui_bootstrap folder with the newest version and the dependencies line for it is also updated to:

"dependencies": {
    "angular-ui-bootstrap": "^1.3.3",

This is DEFINITELY NOT what I want.  So searching further on the web, net me no solution to this.  There are discussions around this topic such as this GitHub issue: https://github.com/npm/npm/issues/5499, which looks like this is still not possible using NPM  and http://stackoverflow.com/questions/26414587/how-to-install-multiple-versions-of-package-using-npm  which again point to JSPM for something like this.  Also found a google group message (couldn’t find it again) that basically tell you to install the old version, copy it to a folder like angular-ui-bootstrap0134 and install it again so it will override the original folder with version 1.3.3.  Very very messy.   I guess a different approach is to create your own copy of npm package for the different versions and use those instead… again not very good solution.

Conclusion

And so… the clear winner here is… JSPM.  Lucky us… we already use JSPM at work Smile.