Open unphased opened 1 month ago
I guess one "workaround" is if we want to save disk with things as they are, we can use n
to install some version of node and then uninstall it with n
. This should remove it then from $N_PREFIX/n/versions
while leaving the whole installed copy under $N_PREFIX/bin
etc. By this perspective $N_PREFIX/n/versions/*
is a simple download cache.
HOWEVER. the behavior of n prune Remove all downloaded versions except the installed version
would contradict this. In the situation where one version of node has been installed via n
, running prune will not remove that one version, but it should if the above were true.
As you worked out, the downloaded versions are cached in $N_PREFIX/n/versions
and also installed (copied) to $N_PREFIX/bin
.
So when you install 10 different versions of Node.js you end up with 11 copies. The active version and the 10 versions in the cache.
HOWEVER. the behavior of
n prune Remove all downloaded versions except the installed version
would contradict this.
This is how prune
was originally implemented (#407). The installed (active) version of node is not deleted from the cache by prune. So only keeping the most relevant version. This lets you try another version of node and get back to where you were.
Following on from my original example, when I get annoyed I have 11 copies of node because I installed 10 different versions, I can run n prune
which will drop me back down to 2 copies. One active, and one in the cache.
It is ok to install a version of node and then immediately delete it from the cache, like:
n 18.15.0
n rm 18.15.0
Yeah I see that to get full storage efficiency we can n rm
the installed version. It's just definitely annoying that prune will take your 11 copies across 10 versions down to 2 identical copies of the installed version when the spirit of prune would here clearly call for bringing it down to just leaving installed intact.
What's even more confusing is this:
n latest
-- installs 22.5.1n 20
-- installs 20n rm 20
n rm latest
Installed node is v20
n ls
shows empty list! At minimum here it should be telling you that v20 is currently installed. Clearly it's an uncommon use case as n is intended for rapid switching. But even the copying step if you switch between two cached versions takes nontrivial time because the executables and files are being actually copied around... somebody has to have an explanation for why we're doing all of these shenanigans when they could be done via changing symlinks.
While I'm complaining about that. If you just
n
and pick 20n
and pick 20n 20
In all these scenarios 20 is already installed but it repeats all the work of copying it in anyway.
In all these scenarios 20 is already installed but it repeats all the work of copying it in anyway.
I understand your desire to skip the install. I used to think that was a good idea too.
The reinstall was a deliberate change in v5.0.0. The goal is a simple predictable behaviour. When you run n install 20
(or pick 20 again) it actually installs 20.
The previous behaviour was it would not install if the active version matches. Great when things are working properly. The problem is if your active version is broken. I found myself suggesting people with problems do things like:
n 8.0.0 # any version other than the one you actually want
n 20.0.0 # the one you actually want, and because it is changing versions it will actually reinstall
n ls
shows empty list! At minimum here it should be telling you that v20 is currently installed.
n ls
shows the local versions available in the cache.
@unphased, thank you for opening this issue.
I'm working on adding node
from n
in Docker and before using N_PREFIX
I tried to install one node
globally in /usr/local
, but it was taking up suspiciously much space.
@shadowspawn thank you for mentioning n rm
, it solved the problem.
ENV NODE_VERSION=20
RUN curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n | bash -s "${NODE_VERSION}" && \
npm install -g n && \
n rm "${NODE_VERSION}" && \
ln -sf "$(which node)" "$(which node)js"
n
is a single bash file, so you could just save the curl download instead of piping it to bash. Something like:
curl -fsSL https://raw.githubusercontent.com/tj/n/master/bin/n -o /usr/local/bin/n
chmod a+x /usr/local/bin/n
n install "${NODE_VERSION}"
n rm "${NODE_VERSION}"
The n
README suggests installing using npm so that you can manage n
along with any other global npm packages, like npm list -g
and npm outdated -g
. This may not be useful in a docker container.
I would like to make it easier to install node with a single command without leaving behind a cache copy. Trying out some option names:
n install --rm auto
n install --cleanup auto
Bug Report
Summary and Repro
I set
$N_PREFIX
to~/.n
from my shell.n seems to install:
~/.n/n/versions/node/22.5.1/
(around 183MB)~/.n/bin
,~/.n/lib
,~/.n/include
,~/.n/share
:❯ du -hs ~/.n/* 109M /home/slu/.n/bin 56M /home/slu/.n/include 18M /home/slu/.n/lib 183M /home/slu/.n/n 72K /home/slu/.n/share
Expected Behaviour
Some sort of symlink from
~/.n/bin/node
to~/.n/n/versions/node/22.5.1/bin/node
and so on. If I install one node version it will consume 180-whatever MB disk. If I install two node versions it will consume 360-whatever MB disk.Actual Behaviour
If I install one node version it will consume 360-whatever MB disk. If I install two node versions it will consume 550-whatever MB disk.
Other Information
I fully expect that there are various issues that have come up in the past that express some desire for
$N_PREFIX/bin/node
and friends NOT to be symlinks. However, I am not sure I buy that, because$N_PREFIX/bin/npm
is itself a symlink, to a "duplicated"$N_PREFIX/bin/../lib/node_modules/npm/bin/npm-cli.js
:Even if the 100+MB
node
executable has to get duplicated on disk why must we also do so forinclude/
andlib/
?