nvm icon indicating copy to clipboard operation
nvm copied to clipboard

Honor .node-version file

Open mnquintana opened this issue 9 years ago • 58 comments

Forgive me if this has been discussed before, but I didn't find anything beyond https://github.com/creationix/nvm/issues/110#issuecomment-40525629.

It would be really nice to see the various Node version managing tools coalesce around a common "version config file", analogous to Ruby's .ruby-version for RVM and rbenv - .node-version. This would basically just be an alias for .nvmrc, since that functionality's already been added. Since n already supports .node-version, this would make it so that regardless of the Node version manager used, there could be some degree of guarantee that the correct version will be used.

mnquintana avatar Aug 04 '15 01:08 mnquintana

When did n add support for node-version?

Which would win if you had both files present?

What about the different version formats that nvm supports - ie, iojs, stable, node, or 0.10, etc - and how do other version managers interact with those? What special formats do they offer that nvm might be forced to interact with?

ljharb avatar Aug 04 '15 01:08 ljharb

When did n add support for node-version?

Ah sorry, my mistake, it wasn't n - it's avn and nodenv. I actually asked the Stack Overflow question about this awhile back.

Which would win if you had both files present?

I think I'd expect .nvmrc to win if both files were present, but I don't really have strong feelings about this.

What about the different version formats that nvm supports - ie, iojs, stable, node, or 0.10, etc - and how do other version managers interact with those? What special formats do they offer that nvm might be forced to interact with?

That's a good question - I'll have to research this a bit.

mnquintana avatar Aug 04 '15 01:08 mnquintana

I'd never heard of nodenv, but avn alone isn't enough for it to be a "common" version file. Do note my answer on that question which I think is a bit better than the accepted one http://stackoverflow.com/a/29545541 :-)

ljharb avatar Aug 04 '15 01:08 ljharb

+1

Rapid, per-project .ruby-version switching with rvm is too useful not to have this for Node.js!

mcandre avatar Aug 24 '15 17:08 mcandre

:+1:

lpil avatar Sep 25 '15 12:09 lpil

I think the idea here is that even though .nvmrc already provides this functionality, having a more generic cross-implementation .node-version file would be beneficial.

As @ljharb pointed out though, interoperability here would require more than just a common filename. iojs, stable, node are also valid version numbers for nvm, but not necessarily for other implementations. I'm honestly not sure how that should be handled. Maybe some discussion with the maintainers of other node versioning-type projects is in order...

Ajedi32 avatar Sep 25 '15 18:09 Ajedi32

If all of nave, n, avn, and whoever else all wants to cleave to nvms "version-ish" format, or, at least is prepared to accept or reject it gracefully (for example, supporting a version number but not a generic tag), that's great. Note that soon I'll have release candidate support for io.js and node, and these will have a different prefix as well, and who knows what the future will bring?

ljharb avatar Sep 25 '15 18:09 ljharb

Just for .nvmrc files - https://github.com/lalitkapoor/nvm-auto-switch - I appreciate any feedback. Thanks!

lalitkapoor avatar Feb 08 '16 06:02 lalitkapoor

Please use github reactions on the original post rather than posting "+1". Fair warning, I'll clean up existing and future comments that simply say that.

ljharb avatar Jun 03 '16 04:06 ljharb

If all of nave, n, avn, and whoever else all wants to cleave to nvms "version-ish" format, or, at least is prepared to accept or reject it gracefully (for example, supporting a version number but not a generic tag), that's great.

That's not a problem, at all...

nvm could use .node-version as an alternative, but still giving preference to .nvmrc.

Project owners could decide to use a wider syntax on .node-version (just the version number, which, I think, it's most of cases) to allow use of any version manager OR use a specialized syntax and prefix on .nvmrc.

I don't even think nvm should care about which file is in use, but just parse .nvmrc or .node-version (in this order).

paulodiovani avatar Jul 27 '16 15:07 paulodiovani

I'm not sure if I even like this idea, but a generic approach to "supporting" node-version directly might be to support a syntax in nvmrc that allows people to read the version string from any other file.

// .nvmrc
file:.node-version

// .node-version
6.3.1

This approach does have some pleasant side effects:

  1. No chasing additional version "standards" once the precedent has been set by supporting .node-version
  2. No questions of precedence
  3. No need to hardcode any subtle differences in support between the two standards since you're essentially making the assumption that the other file is compatible with nvm rather than the other way around.

epixa avatar Aug 07 '16 13:08 epixa

That's not a half-bad idea. However, file:.node-version is a valid alias name, so it'd probably have to be something with a slash in it.

I'll think about that one more.

ljharb avatar Aug 10 '16 00:08 ljharb

.node-version is a much more sane name than .nvmrc

furthermore, I don't see why it shouldn't support both

TylerBre avatar Oct 12 '16 18:10 TylerBre

@TylerBre please don't use ableist terms like "sane".

node-version would work if it was a universal version identifier. However, nvm supports io.js, and aliases, neither of which are necessarily "node" or "universal".

ljharb avatar Oct 12 '16 18:10 ljharb

Even though nvm support io.js, .node-version would still be relevant. And to be fair, nvm stands for "node version manager", and io.js isn't node, it's node compatible. That being said, I think it should be possible to honour .node-version for node versions, and maybe then also support .iojs-version, if that's still relevant for someone.

koenpunt avatar Dec 22 '16 12:12 koenpunt

io.js is node, versions 1-3, after the fact.

You're also missing the most important part, which is "aliases".

ljharb avatar Dec 22 '16 16:12 ljharb

The purpose of .node-version is that you want a static, consistent version. Specifying an alias would defy that purpose.

koenpunt avatar Dec 22 '16 19:12 koenpunt

I agree - which would mean that nvm respecting node-version would have to be limited to static versions only.

What do avn and nodenv support in node-version files? If it's just "a static version, with or without a leading v" then the possibility still remains open that nvm could support that too.

ljharb avatar Dec 22 '16 20:12 ljharb

nodenv differentiates between node and iojs with definitions like 0.10.36 and iojs-1.0.0 (as seen in their README). And it requires that exact version to be installed. Installing of that version can be done by running nodenv install (with the node-build plugin added).

koenpunt avatar Dec 22 '16 20:12 koenpunt

Does nodenv work if you do have a v prefix? (does rvm support the v in .ruby-version?)

ljharb avatar Dec 22 '16 20:12 ljharb

My assumption was it wouldn't work with the v prefix, but it does:

$ cat .node-version
v5.12.0
$ nodenv version
5.12.0 (set by /Users/koenpunt/.../.node-version)

rvm I don't know, but rbenv does, as is about the same as nodenv (nodenv is a port of rbenv)

koenpunt avatar Dec 22 '16 20:12 koenpunt

That's encouraging - it means we could support v1.2.3 or 1.2.3. I'm hesitant to include the "iojs-" prefix, though, since there's no overlap with node - unless every other node version management tool supported it too.

Either way I've filed https://github.com/nodejs/version-management/issues/13, and I think this issue should be blocked on that.

ljharb avatar Dec 22 '16 20:12 ljharb

I just swung by to leave an issue and see if there was any interest in this, but looks like there is!

RVM and rbenv both have their own files and formats but both agree on .ruby-version, and it would be lovely if nvm and nodenv could agree on a common file too, even if nothing changes by default.

Here's how RVM load the file:

.rvmrc - shell script allowing full customization of the environment, .versions.conf - key=value configuration file .ruby-version - single line ruby-version only Gemfile - comment: #ruby=1.9.3 and directive: ruby "1.9.3"

So, we could very easily add another function to check for .node-version if there is no .nvmrc, agreed?

philsturgeon avatar Oct 05 '17 16:10 philsturgeon

Here you go! https://github.com/creationix/nvm/pull/1625

philsturgeon avatar Oct 05 '17 16:10 philsturgeon

I'd never heard of nodenv, but avn alone isn't enough for it to be a "common" version file.

fnm also supports .node-version

https://github.com/fisherman/fnm/blob/503b07d3b419908409373699c227c4baf32b4b7b/functions/__fnm_read_fnmrc.fish#L4

franciscolourenco avatar May 25 '18 08:05 franciscolourenco

+1 would love this, colleagues and I use different version managers - the support will help keep us in sync.

dmil avatar Oct 29 '19 21:10 dmil

.node-version is also supported by the nodejs plugin for ASDF, a universal version manager (nodejs, ruby, etc etc)

cmitz avatar Oct 31 '19 16:10 cmitz

nvs also supports .node-version

it's kinda annoying needing to have 2 files because different people have different preferences.

brunolm avatar May 18 '21 14:05 brunolm

This repo offers a pretty comprehensive growing list of the version managers that honor .node-version: https://github.com/shadowspawn/node-version-usage

Perhaps you could honor both? 🤷🏻‍♂️ Detect .nvmrc first and support more advanced features there but, if that isn't present, detect .node-version and only support its subset of features? 🤔

I know supporting multiple can be a slippery slope but it feels like a reasonable maintenance burden at the moment (to me, as an admitted non-maintainer 😅). ❤️

JamesMGreene avatar Nov 23 '21 16:11 JamesMGreene

Yes, the growing list means it's almost certainly never going to be possible for this specific file to become a standard.

ljharb avatar Nov 23 '21 16:11 ljharb

zOMG 2021 and this shit still doesn't support anything but .nvmrc‽ 🤯

sshaw avatar Dec 09 '21 18:12 sshaw

@sshaw that's a hostile comment, and yes, the date has no bearing on whether there's support for a nonstandard file. we don't support anything right now but our own file, since there's no standard, and that's what every other tool should be doing too.

ljharb avatar Dec 09 '21 18:12 ljharb

@ljharb ... the date has no bearing on whether there's support for a nonstandard file. we don't support anything right now but our own file, since there's no standard, and that's what every other tool should be doing too.

A lack of a standard shouldn't inhibit interoperability especially when other tools i.e., your competitors, have implemented what I think is fair to call "working support" for them and, in some cases on top of their own file.

What is the (edge) case that makes the entire case for supporting .node-version unreliable or, a non-starter due to "lack of standard"?

sshaw avatar Dec 09 '21 18:12 sshaw

Interoperability is only POSSIBLE with a standard. There isn't any such interoperable standard defined for that file.

Some other maintainers may be willing to offer "working support", but I'm unwilling to ship anything that doesn't have full, eternal support.

ljharb avatar Dec 09 '21 18:12 ljharb

Interoperability is only POSSIBLE with a standard.

I've been using asdf and at times nodenv with .nvmrcs for several years. Looks to be pretty operable to me! Maybe I was dreaming? Was curious about the faulty cases. Aliases you mention but the others: who knows!

sshaw avatar Dec 09 '21 18:12 sshaw

I'm very glad your experience has been positive. I do hope you understand that the sum of "anecdotes" is not "data", though, and that what's far more likely is that those who have encountered problems have simply not used that filename to avoid them.

Aliases (user-defined ones; version-manager-defined ones, like nvm's iojs or node; node-defined ones like LTS names or release channel names), fuzzy specifiers (like 14 or 14.1 instead of the fully-qualified version number), to name a few.

ljharb avatar Dec 09 '21 19:12 ljharb

I added this to my zsh profile to autoload a node version from either .nvmrc or .node-version (with fallback to default if neither found):

# Set node version
function change_node_version() {
  local nvmrc_path="$(pwd)/.nvmrc"
  local node_version_path="$(pwd)/.node-version"
  if [ -f $nvmrc_path ]; then
    echo ".nvmrc file exists."
    version="$(cat "$nvmrc_path")"
    nvm use $version
  elif [ -f $node_version_path ]; then
    echo ".node-version file exists."
    version="$(cat "$node_version_path")"
    nvm use $version
  else
    echo "Neither .nvmrc nor .node-version files exist."
    nvm use default
  fi
}
chpwd_functions+=(change_node_version)

alex-latham avatar Mar 15 '22 21:03 alex-latham

If you are interested in augmenting the existing function mentioned in the README, I highlighted the lines that you need to copy from @alex-latham's solution:

  load-nvmrc() {
    local node_version="$(nvm version)"
    local nvmrc_path="$(nvm_find_nvmrc)"
+   local node_version_path="$(pwd)/.node-version"

    if [ -n "$nvmrc_path" ]; then
      local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

      if [ "$nvmrc_node_version" = "N/A" ]; then
        nvm install
      elif [ "$nvmrc_node_version" != "$node_version" ]; then
        nvm use
      fi
+   elif [ -f $node_version_path ]; then
+     version="$(cat "$node_version_path")"
+     nvm use $version
    elif [ "$node_version" != "$(nvm version default)" ]; then
      echo "Reverting to nvm default version"
      nvm use default
    fi
  }

cmolina avatar Mar 22 '22 19:03 cmolina

I find nodenv[-install] to be highly reliable these days. Wonder if that supports querying desired node version ranges from package.json.

On Tue, Mar 22, 2022, 2:52 PM Carlos Molina A @.***> wrote:

If you are interested in augmenting the existing function mentioned in the README https://github.com/nvm-sh/nvm#zsh, I marked the lines that you need to copy from @alex-latham https://github.com/alex-latham's solution:

load-nvmrc() { local node_version="$(nvm version)" local nvmrc_path="$(nvm_find_nvmrc)"+ local node_version_path="$(pwd)/.node-version"

if [ -n "$nvmrc_path" ]; then
  local nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")

  if [ "$nvmrc_node_version" = "N/A" ]; then
    nvm install
  elif [ "$nvmrc_node_version" != "$node_version" ]; then
    nvm use
  fi+   elif [ -f $node_version_path ]; then+     version="$(cat "$node_version_path")"+     nvm use $version
elif [ "$node_version" != "$(nvm version default)" ]; then
  echo "Reverting to nvm default version"
  nvm use default
fi

}

— Reply to this email directly, view it on GitHub https://github.com/nvm-sh/nvm/issues/794#issuecomment-1075575965, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAABJRBPHXO5HNZPNAF7PD3VBIQIDANCNFSM4BMT6JZA . You are receiving this because you commented.Message ID: @.***>

mcandre avatar Mar 24 '22 23:03 mcandre

@ljharb

Is there any chance at all you would be willing to change your mind here? There is real developer pain caused by nvm's refusal to interop. This schism creates fragmentation pain felt by end users. The problem gets exacerbated further for non-development folks like designers and PMs who may want to try running apps locally and get tripped up when setup docs just say to install any node version manager of your choice. As you'd expect, nvm is the top search result for "node version manager".

I'd argue that .node-version is already a de-facto standard (albeit, with gaps in specification). There is value in adherence to conventions. Markdown had no formal spec and was loaded with ambiguous edge cases, but it's become almost universally accepted. Sure, there are localized flavors of it now, but the commonalities of Markdown still deliver value. Even JSON didn't really have a formal standard till 2013, long after it already had wide usage.

I totally understand your perspective of wanting to only build on solid foundations. My perspective here is that more harm is done by not supporting .node-version. The conventions around .node-version are to support a subset of what .nvmrc supports. Just treating .node-version the same as .nvmrc would address the interop concerns.

If you're dead set against making this default behavior, could you let this work off an env variable?

bilalq avatar May 12 '22 20:05 bilalq

@bilalq there's no "refusal" to interop - no interop exists, because there's been no group consensus reached about the specification for the .node-version file.

A defacto standard requires a predominant subset of semantics, which nobody's illustrated exist. Is the "v" prefix required, optional, or forbidden? Is a semver version triple required, or can a major.minor or major be specified? In the latter two cases, is a trailing dot required, optional, or forbidden?

The most POSSIBLE harm is done by implementing a nonstandardized potential standard - and this includes every existing tool that supports this wildly underspecified filename.

ljharb avatar May 13 '22 02:05 ljharb

The predominant subset of semantics, supported by all utilities I have examined, is:

  • no v prefix
  • semver triple
  • unix line ending

https://github.com/shadowspawn/node-version-usage

shadowspawn avatar May 13 '22 03:05 shadowspawn

I'd recommend following Robustness Principle, and implementing what gives people value, recognising commonly used patterns that may become standardised in the future. Even if there was a standard, according to the robustness principle it would be a good practice if nvm accepted more formats beyond standardised. There's no reason for gatekeeping just because there's no agreed version - unsurprisingly other tools & IDEs found their way to help people, by just implementing what seemed a good judgement of most used values.

TeoTN avatar Jul 02 '22 13:07 TeoTN