Latest news about Bitcoin and all cryptocurrencies. Your daily crypto news habit.
tl;dr: fnm is a very fast Node.js version manager, ~40x faster than NVM. It supports .nvmrc files and Fish shell out of the box. It works on Linux and Mac and distributed as a single executable - and it is open source on GitHub!
So,
Two weeks ago, I had opened a new tab on my terminal and complained in agony: âOh dear god! Every time I open a new terminal it takes like one second!â. My teammates looked at me funny. âThis is clearly sub-optimal and hurts my focus, and I believe itâs NVMâs fault.â
I found itâs NVM that is at fault after I did a search around my .zshrc file, checking which line takes the most time. It was NVMâs initialization. I have been using NVM for years, and I always wanted to write a simple replacement, because my use cases are pretty simple:
- I want to be able to download any Node version (like nvm install)
- I want to be able to switch between them easily (like nvm use)
These tasks arenât hard to solve. Node.js binaries are distributed in tarballs on their website, and switching versions shouldnât be more than just changing a symbolic link around. So, why is NVM so slow?
I thought about writing it as a simple Bash script, just like NVM, but I wanted it to be interesting and fun. Also, not all machines have Bash installed, or there might be problems integrating with Bash. I have used Fish shell for years, and in order to use NVM, I had to use a wrapper that fixes things. It wasnât easy. Using a real executable, on the other hand, would work on every shell!
The first prototype
My first prototype was a TypeScript app. I packaged it with Zeitâs pkg, making it a self-contained executable, because I didnât want to have dependency on Node. I wanted it to work on a system without Node installed (so the first version of Node would be installed using fnm!)
Nodeâs startup time wasnât good enough for me. Just spawning a âhello worldâ takes around 200ms, which is good for servers, and for command line utilities that you donât use frequently, maybe, but some people use nvm on every cd, so their Node version will always be in sync. 200ms penalty for every cdis madness and would make the tool unusable.
So it seems like I need to write it in a language that is compiled (so no dependencies on the host system), and with a fast boot time. Four languages came to mind: Go, Rust, Crystal and Reason/OCaml.
A Native Reason App
I chose Reason for many Reasons (hehe), some of them are written in another post. I had used esy and pesy, two awesome packages that make the development workflow for native Reason/OCaml apps easy-peasy for Node.js developers.
esy works like a super-powered yarn: it installs packages from npm or OPAM (OCaml package manager) and stores it in a global cache. It also manages a sandbox for the OCaml runtime/dependencies for you, so different OCaml installations wonât interrupt each other. pesy generates build configurations for Dune, OCamlâs build tool, right from the package.json file.
When using both packages, it feels just like Node developmentâââeverything works with a single package.json file, with minimum configurations. It can also help other Node devs, just like it helped me, to contribute to the project, because Reason syntax is very close to JSâ, and the toolchain feels veryJavaScript-ish.
I had built the first prototype, and tested its performance. I had two test files, one using NVM and one using fnm. Both tests spawned a plain Bash, called the âinitializationâ of the target (NVM/fnm), and then switched to the Node version specified in .nvmrc file in the directory using the target. I ran it 10 times for each binary, and the results were amazing:
- NVMâs test case was around 600ms on my machine
- fnmâs test case was around 15ms on my machine
So in that test, on my MacBook Pro, fnm was 40 times faster than NVM. Thatâs pretty huge, despite not being very scientific.
A real-time animated video is on the repoâs README
Releasing to Public
When I had started working on fnm, I joined the Reason Discord server, and asked some help from people. I found that community is so nice. When I decided to release, I wrote a short message on the #native-development channel and immediately got great feedback, telling me itâs a great idea.
The community aspect is such an important part of JavaScript, and Reasonâs community feels even nicer than JSââââmaybe because the community is still small, but it is very welcoming.
I released fnm to GitHub as open source, tweeted about it and went to bed. When I woke up,
- My twitter notifications were on fire đ„
- The repo had more than 500 stars đŻđŻđŻđŻđŻ
- fnm was #1 on HackerNews đ
- No one on Reddit/HackerNews called me an idiot! đ€Ą (a rare sight)
Thatâs a big deal.
What Now?
fnm has some features still missing. Here are only a few things we want to add:
- Windows support
- Version aliases
- Support downloading latest LTS
- Per-shell usage
- Drop dependency on tar and curl
- ⊠and more!
So if you feel like youâre ready to use it and start working faster, or youâre a JS/Reason developer willing to contribute to an open source project, download fnm and join us on GitHub!
đ fnm: Fast and Simple Node.js Version Manager was originally published in Hacker Noon on Medium, where people are continuing the conversation by highlighting and responding to this story.
Disclaimer
The views and opinions expressed in this article are solely those of the authors and do not reflect the views of Bitcoin Insider. Every investment and trading move involves risk - this is especially true for cryptocurrencies given their volatility. We strongly advise our readers to conduct their own research when making a decision.