Asset-builder pulls in dependency of dependency inconsistently

I copied a WIP Sage-based theme from my local environment to my company’s prod environment. Everything appeared to work correctly except that Bootstrap JS was being added to dist/main.js twice.

First, I removed all JS files from overrides.bootstrap-sass in bower.json. No luck. All Bootstrap JS was still being loaded into dist/main.js.

I then re-read this line in the roots docs:

Any main JS dependencies from Bower packages are also included in the primary JavaScript file.

It turns out that one of my dependencies, bootstrap-touchspin, declares bootstrap as a dependency in its bower.json:

"dependencies": {
  "jquery": ">=1.9.0",
  "bootstrap": ">=3.0.0"

I overrode this in my bower.json to remove bootstrap (I’m using bootstrap-sass, of course):

"bootstrap-touchspin": {
  "dependencies": {
    "jquery": ">=1.9.0"

This seems to have solved the problem. However, one mystery remains: Why is this only happening in one environment and not the other?

The only relevant difference I have been able to find between the copied theme and the original is that bootstrap-touchspin has been patched to include a missing main item in its bower.json, but I can’t see how that could cause the issue I describe above.

Different versions of Node.js? You could use nvm to use the same version on Node on both, and introduce npm shrinkwrap.