Global npm Module Weirdness

I just installed node 8.9.1 with nodenv. Then I wanted to get my global packages installed to more-or-less match what I had with my previous version of node (v6.11.3).

Running npm list -g --depth=0 with node 6.11.3 active gives me:

❯ npm list -g --depth=0
├── eslint@4.7.1
├── eslint-config-airbnb-base@12.0.0
├── eslint-config-prettier@2.5.0
├── eslint-plugin-import@2.7.0
├── eslint-plugin-json@1.2.0
├── eslint-plugin-prettier@2.3.1
├── generator-code@1.1.20
├── gulp@3.9.1
├── npm@3.10.10
├── prettier@1.7.3
├── prettier-eslint@8.2.0
├── vsce@1.31.1
└── yo@2.0.0

So with node 8.9.1 active I ran npm i -g eslint gulp prettier prettier-eslint yo generator-code to start installing a bunch of — but not all of — the global packages that I wanted.

Now for the weird part: Running npm list -g --depth=0 to see the current state of the world gives me this:

❯ ng # <-- a handy alias for `npm list -g --depth=0`
├── generator-code@1.1.22
├── gulp@3.9.1
├── npm@5.5.1
├── prettier-eslint@8.2.2
└── yo@2.0.0

eslint isn’t listed as a global package! But I have it installed:

❯ which eslint; and eslint -v

I looked a little deeper and found eslint installed as a dependency of prettier-eslint (which, by the way, is not a module that I actually wanted to have installed globally):

❯ npm list -g --depth=1
├─┬ prettier-eslint@8.2.2
│ ├── ...
│ ├── eslint@4.11.0

And further, digging into where nodenv actually stores the globally installed modules, in this case ~/.nodenv/versions/8.9.1/lib/node_modules, I see that eslint is indeed there at the top level!


So the question is:

Why doesn’t npm list eslint as a top-level globally installed module when it seems as though it is one?

The follow up question is: Why does it bother me as much as it does that eslint doesn’t show up in that list of global modules even though everything works as though it is a top-level global module?

The Fix

How to fix this “problem”? One option is to just blow away all of the globally installed packages by running this a couple of times:

npm ls -gp --depth=0 | awk -F/ '/node_modules/ && !/\/npm$/ {print $NF}' | xargs npm -g rm

That’s extreme and is likely something that you wouldn’t want to do in most situations.

The other option is to remove the package that has eslint as a dependency, which is a package I didn’t want to have installed in the first place: npm -g rm prettier-eslint

Now the world is happy again:

❯ ng
├── eslint@4.11.0
├── generator-code@1.1.22
├── gulp@3.9.1
├── npm@5.5.1
├── prettier@1.8.2
└── yo@2.0.0

Final Note

At this point reinstalling prettier-eslint works and eslint still shows up as a global package.