Hacker News new | comments | ask | show | jobs | submit login
Show HN: Fnm – Fast and simple Node.js version manager built in ReasonML (github.com)
87 points by schniz 23 days ago | hide | past | web | favorite | 69 comments

Great work, but you'd have to pry asdf out of my cold, dead hands.


I used nvm for years, but my development workflow became more and more terminal-oriented to the point I was spawning new ones several times an hour. Nvm took almost a second to launch, easily consuming 99% of the startup time for each shell. I tried writing some custom code to lazy load nvm only when I needed it which worked alright, but I ended up switching to Asdf because it loads almost instantaneously and haven’t looked back. The fact that it supports managing multiple different tools is a nice bonus, but I really only use it for node.

I think I started using it for much the same reason; I was having trouble with the official node installer. But once I uninstalled rvm as well, I was sold. Now I can have a project with a specific elixir/erlang/node version written into my `.tool-versions` file, and I don't have to worry about anything.

I hate how it bears the same name as the de-facto standard Common Lisp build tool, ASDF.


I have to read the README twice to see what is it about. What is extensible version manager? Managing what exactly. So I guess it's the reason asdf is not popular

It replaces gvm/rbenv/pyenv/nvm/etc. with a single CLI. Saves you from having to use multiple shell completion scripts, bashrc entries and CLIs. Useful if you work with multiple dev languages on your computer.

And nowhere in the README tells me about that. Your first sentence immediately makes it clear

asdf maintainer here. We are in the process of re-organizing the README and all of the documentation. In it's present state the README isn't particularly clear about what asdf is and why it is useful. One of the maintainers already has a PR out to fix this - https://github.com/asdf-vm/asdf/pull/441

If you have any suggestions on what the readme should say feel free to open an issue or a small PR.

I'm sorry, I could have sworn the README used to have a snappy description.

Think of it like a Swiss Army knife of version managers that can handle all the languages you use, per-project. And it's all just bash scripts, and installs everything into a visible place on your drive.

It worked rather badly with Haskell last time I checked (Darwin, Fish shell).

I'm sorry to hear that but I'm happy to help if there is anything I can do as a maintainer. The Haskell plugin isn't maintained by the core team, and it may have some issues of it's own that need to be fixed. If there was something specific that caused you trouble let me know and I'll see what I can do to get it addressed.

Thanks a lot for the reply and willingness to help, but I'm not using anything Haskell related at the moment. Might submit some issues in the future though.

To be fair, the entire Haskell tool chain is finicky as heck in my experience.

I use nvm currently. Can I ask how this compares to nvm, perhaps issues with nvm that it tackles? Is it performance? :o

this really does need a pitch comparison vs nvm. when I first saw yarn I switched almost instantly from npm because the pitch and improvement were clear

Is there still any reason to use yarn today?

we didn't move back since we use lerna with yarn workspaces. few more reasons are offline package cache and pnp

edit: also just read the v2 roadmap that is on the top of HN now - lots of great new features coming up which only reinforces our decision to stick with yarn

Hey! fnm is a very simple and (very) fast node version manager. On my machine, `nvm init`/`nvm use` takes around 600ms - this means each time you spawn a new shell you have a ~600ms penalty.

The gif on the README is real time (it's a screen recording) - so installations are fast, and every command that works locally is extremely fast.

So, tl;dr, fnm is built with performance in mind

Thanks! Perhaps a caption noting this would improve the pitch :)

The problem I have with nvm is speed (running it at shell startup introduces a very noticeable delay), and integration with other shells - it's always been a pain to get it running with fish.

I generally use only a single node version, and therefore don't use the nvm command much, so I've solved the slow shell init by not loading nvm at all, and instead, just set the PATH.

    export PATH=~/.nvm/versions/node/v11.6.0/bin:$PATH
Downside is that you have to bump the version occasionally but it's worth the fast shell startup.

I currently have this problem on my zsh setup - is there any easy fix for it?

idk about zsh, but for fish there is https://github.com/FabioAntunes/fish-nvm which delays executing nvm until you use one of the node binaries. Essentially, node is aliased to `nvm activate && node`

I second this question. I'm using nvm almost everywhere and have never had issues, nor did I ever experience it as slow.

I'm pretty sure `nvm` supports more use cases than fnm right now, as it is a much more mature project. However, it is slower in orders of magnitude.

It does support `.nvmrc` files so my use cases have been fulfilled with fnm - but if yours wasn't implemented yet - you are more than welcome to open an issue and we'll try to tackle it.

Also, fnm is a single executable, therefore it is very easy to install and works across all shells (no need for wrappers in `fish` shells, for instance). Just put it in your path and you're good to go!

I quit using nvm when it has become a pain to run it in non interactive situations such as from cron, from pm2 and from monit config. It needs changes on how it's launched all over and it was just not worth it.

I'm using nave, also with no issues. A "why fnm vs nvim / nave" section in the readme would be useful.

Wait, I assumed this will be a js-app, but it actually is a executable binary?

Is that the courtesy of https://github.com/jordwalke/pesy ?

For some time I wanted to try ReasonML for server-side development, but for some reason I assumed, that most of the ecosystem would be node.js based.

Hi I'm Jordan and I work on Reason.

pesy is just a utility I made to help people create new native Reason projects (like fnm) quickly and easily. It's fun.

fnm is a native Reason app. We haven't advertised much of Reason's (OCaml's) native capabilities because we wanted to make sure we've built out a lot of the tooling that makes native development easy - for example https://esy.sh. Now that a lot of this native tooling is becoming polished, I hope you'll probably start seeing more projects like fnm.


I looked at Reason several months ago and my impression was, that if you want to do frontend stuff with bucklescript, you are one git-pull and npm install from a working scaffold, but if you want Reason with ocaml for native stuff, you would mostly be scaffolding yourself.

I am really glad I was mistaken :)

Several months ago that was probably correct. Recently, we've released new tools like esy that make it... easy, especially if you come from a JS background or are familiar with JS tooling. There's still a lot to solve, and native is just inherently harder than targeting JS, but a lot of progress has been made recently, and there's more to come.

Reason is merely a new syntax on OCaml. You can use BuckleScript (BS) to compile to JS, or not use BS to compile to native.

There exists a fast http server in native OCaml:


Let's be a little more specific. "Reason Syntax" is merely a new syntax on OCaml, but ReasonML in general has a much larger scope - which includes every part of the toolchain/workflow up to and including package management, IDE integration, source formatting etc and more.

So Reason is to OCaml a little like Elixir is to Erlang - newer syntax, better tooling, same great foundation.

httpaf is quite low level. We need more abstractions on top of that for daily server development

One recent project which builds a usable layer on top: https://github.com/ostera/httpkit

The ReasonML ecosystem is quite confusing for newcomers. ReasonML could be compiled to a binary out of the box thanks to the OCaml toolchain. Pesy is a tool for making native development easier. Regardings Javascript compilation backend, you only hear about that because it's what the ReasonML team selling.

And I get that, I think I heard somebody from Reason community to say on some podcast once "We want to get the frontend stuff right first", or something along those lines :-)

That makes more sense to me now why doing server side reason compiles to a node.js app and not a more performant OCaml app. Server is not a priority yet.

Server side reason can already compile to native binaries (thanks to the OCaml compiler). While maybe smaller than the npm ecosystem there are a lot of high quality packages available on the OCaml ecosystem [1] that allow for a very pleasant server side development experience. For example https://github.com/rgrinberg/opium is a really nice high level toolkit. There are database bindings to Postgres, Mysql and the like, and high level interfaces to them like https://github.com/paurkedal/ocaml-caqti

[1] http://opam.ocaml.org/packages/

I feel you - it seems that most ReasonML blogposts are around JavaScript usage, but this is completely native and therefore faster (no VM necessary)

Maybe I'm completely out of the loop, but what's the deal with running multiple versions of Node?

What particular problems or projects do you have where this is a pressing necessity?

I just install latest LTS and keep that up to date, and I've yet to find a single thing not working.

Sometimes you're limited in production by whatever version the OS supports. In the case of Debian installing nodejs doesn't necessarily land you the latest and greatest. The same happens with Python as well. I wish they had a good way to abstract this in Debian and I'm surprised Ubuntu hasn't fully resolved it, I mean Ubuntu does have Snap but I can't trust Snaps fully if the language vendors aren't backing the only available Snaps. But to account for systems where the only version of Node or Python, or whatever is a specific version, you need systems like this.

Why don't you just install the official 'deb' package with the version of your choice?


You can absolutely install the newest version of Python and Node on Debian. It is a little harder than just an `apt-get install`, but very possible.

Of course you can install it. In many environments it's not considered maintainable to deviate from the distro provided and supported version. Especially when you have support contracts from your OS vendor.

If devs want something different from the distro provided libs we typically ask that they use containers or otherwise vendor them.

Ideally we would like our software to depend on the system for the bare minimum and security critical libs like OpenSSL so that Ops is free to switch out the underlying platform with minimal friction.

I have a development server that has some projects mainly written by someone else and one of them specify an old version of nodejs as dependency which breaks by using latest LTS (and I'm too lazy to figure out how to make someone else's code to work on latest LTS) but I don't want to turn nodejs for the entire server to an old LTS.

When I write lambda code for my job, our code currently only supports the node 6 for it's runtime (our system automatically deploys it). I use nvm to help test my code all the time while still having the ability to switch to a more current node for other projects

Are you running your projects directly on your machine? Your’re not using a VM or containers? Don’t you have the “but it works on my machine” problem?

We only run it for quick tests. This is custom code that our main application uses for custom logic that is different for each customer. We can't build it into the main product because not everyone wants/needs it. We always test on the lambdas directly, but we just dev on our machine as that's sometimes quicker.

We never had that issue with node

Here's a couple of use cases:

You maintain a library and you support more than just the latest version of Node. You switch to test compatibility.

You work on a project with a team. Some members of the team work on other projects with other versions of Node. They need to be able to switch.

It's nice to have this when you need to debug issues which only occur on certain versions. A good example would be the recent change of the c++ addon api, which caused my code to crash on some installations while it worked fine on others.

For us, it's about developing on the same node version used in production. That's necessary if you're not deploying to a containerized environment or you're using something completely out of your control like AWS Lambda.

the main reason i use nvm is because its the only way i can use npm i -g.....

You dont need to nvm to do that. You just need to set an alternate "global" path inside your home-directory, instead of one in /usr/lib/node which requires root.


How does it compare to n?


Yea, I use n as well. Seems to do its job and stay out of my way.

At this point, I use Docker for almost every project that I work on, and one of the reasons is that Docker allows me to create a separate environment for each project. I don't need to learn multiple version managers, and it works equally well for non-language tools, like Postgres and Redis.

As a Python developer, and when docker is not an option, nodeenv is the perfect solution for me, to the point that I have a bash function specifically for creating a Python virtualenv and then installing nodeenv on top.

Naming conflict with Fish Node Manager (https://github.com/jorgebucaran/fish-nvm), a wrapper of NVM for the fish shell.

Yup came here to say this, although I have recently had issue with the Fish Node Manager which had me revert to using nvm.

Issues which made it unusable completely every time I tried to use node it could no longer find the node/npm binaries.

Looks like a great project, but really needs documentation.

The only option other than reading the code I have now is screen-capturing the last frame of the gif an looking at what commands were used. Really?

Hi! I guess you're `whyboris` from GH. Thanks again for the feedback :D Just noting that I have added a small piece of documentation. The CLI itself also has `--help` flag, and it works also for every subcommand (`nvm install --help` for instance)

What's wrong with nodenv?

The problem sounds like why do we have nvm, n, nodenv, asdf (and some more) and now fnm?


How did you create the .svg terminal animation?

yes! such a wonderful library. I've taken the ideas from `create-react-app` :)

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact