每次目录上有.nvmrc文件时自动运行`nvm use`

Gab*_*vel 53 javascript shell node.js nvm

如何配置我的shell,以便nvm use每次目录上有.nvmrc文件时自动运行,并在没有.nvmrc文件时使用最新版本或全局配置?

Rot*_*eti 44

如果你使用zsh(z shell):

在具有.nvmrc文件的目录中自动调用'nvm use'

每当你输入一个包含.nvmrc文件的目录时,将它放入$ HOME/.zshrc中以自动调用nvm,该文件带有一个告诉nvm使用哪个节点的字符串:

# place this after nvm initialization!
autoload -U add-zsh-hook
load-nvmrc() {
  local node_version="$(nvm version)"
  local nvmrc_path="$(nvm_find_nvmrc)"

  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 [ "$node_version" != "$(nvm version default)" ]; then
    echo "Reverting to nvm default version"
    nvm use default
  fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc
Run Code Online (Sandbox Code Playgroud)

更多信息:https://github.com/creationix/nvm#zsh

  • 这对我来说非常有效,但对“cd”造成了性能影响,因为它在每次更改目录时都会运行。我添加了 `[[ -a .nvmrc ]] || return` 到 load-nvmrc() 的第一行,这显着提高了它的性能 (9认同)
  • 如果您使用的是“Powerlevel10k”,请不要忘记在“nvm use”之后添加“--silent”,以避免在 zsh 初始化期间出现控制台输出警告 (4认同)
  • @Belgabad它的性能更高,因为使用您的行,脚本不会检查父目录中的“.nvmrc”,并且当您从项目目录中“cd”时,它也不会返回到默认的“node”版本。 (2认同)

dev*_*ius 32

如果您使用bash,可以将其添加到您的~/.bashrc文件中:

enter_directory() {
  if [[ $PWD == $PREV_PWD ]]; then
    return
  fi

  PREV_PWD=$PWD
  [[ -f ".nvmrc" ]] && nvm use
}

export PROMPT_COMMAND=enter_directory
Run Code Online (Sandbox Code Playgroud)

  • 这对我来说破坏了direnv。 (2认同)

Gab*_*vel 23

我刚刚发现了Node.js的自动版本切换https://github.com/wbyoung/avn,您可以使用它.

您也可以关注此主题 https://github.com/creationix/nvm/issues/110

  • 这令人沮丧..工具堆栈深度没有限制吗?node→npm→nvm→avn,然后备份.*叹气*我会打球,但每次破解我的热情都在减弱.(并且感谢链接,当然,gabo.) (21认同)
  • 不幸的是,[avn 不再维护](https://github.com/wbyoung/avn/issues/109),并且 @hraban 反对是有效的 - 而且,`nvm` 不依赖于 `npm/node`设计,因此添加另一个需要“node”的工具似乎是不明智的。IMO direnv,根据 [R. Haluk Öngör 的回答](/sf/answers/4346654931/) 是最好的方法。direnv 与 shell 无关,几乎没有依赖项(更重要的是,不依赖于它应该管理的工具),并且更通用,同时仍然可用且安全。 (2认同)

Adr*_*o P 21

来自@devius的优秀答案.

我只是扩展它,以便在.nvmrc没有它的情况下将目录留给另一个目录时可以恢复为默认版本.

~/.bashrc:

#
# Run 'nvm use' automatically every time there's 
# a .nvmrc file in the directory. Also, revert to default 
# version when entering a directory without .nvmrc
#
enter_directory() {
if [[ $PWD == $PREV_PWD ]]; then
    return
fi

PREV_PWD=$PWD
if [[ -f ".nvmrc" ]]; then
    nvm use
    NVM_DIRTY=true
elif [[ $NVM_DIRTY = true ]]; then
    nvm use default
    NVM_DIRTY=false
fi
}

export PROMPT_COMMAND=enter_directory
Run Code Online (Sandbox Code Playgroud)

  • 通过使用`VERSION = $(cat .nvmrc);进行了修复 nvm使用$ VERSION` (2认同)

cal*_*lum 16

我尝试了很多解决方案,但没有一个能按照我想要的方式工作,所以我写了自己的:

ZSH 功能自动切换到正确的 Node 版本

据我所知,这是唯一满足以下所有标准的:

  • 通过搜索目录树找到最接近的版本,保证您始终使用正确的版本.nvmrc(就像nvm use);
  • 可以处理任何有效的.nvmrc格式;
  • 如果没有安装的版本满足以下条件,则会明确警告您.nvmrc
  • 如果树上default没有任何地方,则假设您想要;.nvmrc
  • 如果您已经使用正确的 Node 版本,那么它是完全安静且快速的。


小智 8

当您使用 shell 游泳时,以下是只要目录中有 a 就fish如何运行:nvm use.nvmrc

# TODO: save this as `$HOME/.config/fish/conf.d/use_nvmrc.fish` 

# HOW IT WORKS
# `nvm use` whenever .nvmrc is present in $PWD when using fish shell
# when traveling deeper, use the parent .nvmrc unless otherwise set
# also go back to default nvm when leaving the nvmrc-specified zone

function set_nvm --on-event fish_prompt
    # runs whenever the fish_prompt event occurs
    # if the current directory hasn't changed, do nothing
    string match -q $PWD $PREV_PWD; and return 1

    # if the current directory is within the previous one where we found an nvmrc
    # and there is no subsequent .nvmrc here, do nothing, we are in the same repo
    string match -eq $PREV_PWD $PWD; and not test -e '.nvmrc'; and return 1

    # if we clear those checks, keep track of where we are
    set -g PREV_PWD $PWD

    if test -e '.nvmrc'

        # if we find .nvmrc, run nvm use
        nvm use

        # and remember that we used that node
        set NVM_DIRTY true

    else if not string match $NVM_DIRTY true

        # if we have set nvm and have stepped out of that repo
        # go back to default node, if not already on it
        not string match -eq (nvm current) (nvm alias default); and nvm use default

        # and clear the flag
        set NVM_DIRTY
    end
end
Run Code Online (Sandbox Code Playgroud)


d4n*_*yll 7

这个答案来自官方的nvm文档

将以下内容放在您的末尾$HOME/.bashrc

find-up () {
    path=$(pwd)
    while [[ "$path" != "" && ! -e "$path/$1" ]]; do
        path=${path%/*}
    done
    echo "$path"
}

cdnvm(){
    cd "$@";
    nvm_path=$(find-up .nvmrc | tr -d '[:space:]')

    # If there are no .nvmrc file, use the default nvm version
    if [[ ! $nvm_path = *[^[:space:]]* ]]; then

        declare default_version;
        default_version=$(nvm version default);

        # If there is no default version, set it to `node`
        # This will use the latest version on your machine
        if [[ $default_version == "N/A" ]]; then
            nvm alias default node;
            default_version=$(nvm version default);
        fi

        # If the current version is not the default version, set it to use the default version
        if [[ $(nvm current) != "$default_version" ]]; then
            nvm use default;
        fi

        elif [[ -s $nvm_path/.nvmrc && -r $nvm_path/.nvmrc ]]; then
        declare nvm_version
        nvm_version=$(<"$nvm_path"/.nvmrc)

        # Add the `v` suffix if it does not exists in the .nvmrc file
        if [[ $nvm_version != v* ]]; then
            nvm_version="v""$nvm_version"
        fi

        # If it is not already installed, install it
        if [[ $(nvm ls "$nvm_version" | tr -d '[:space:]') == "N/A" ]]; then
            nvm install "$nvm_version";
        fi

        if [[ $(nvm current) != "$nvm_version" ]]; then
            nvm use "$nvm_version";
        fi
    fi
}
alias cd='cdnvm'
Run Code Online (Sandbox Code Playgroud)

这是对以下方面的改进:

该别名将从当前目录中搜索“ up”以检测.nvmrc文件。如果找到它,它将切换到该版本。如果不是,它将使用默认版本。


小智 6

使用direnv 的另一个解决方案。Direnv 随 OS X 和许多发行版一起提供,因此无需安装。

根据您使用的 shell,将这两行添加到您的 .zshenv 或 .bash_profile 中:


export NVM_DIR="$HOME/.nvm" # You probably have this line already
export NODE_VERSIONS="${NVM_DIR}/versions/node"
export NODE_VERSION_PREFIX="v"
Run Code Online (Sandbox Code Playgroud)

将 .envrc 文件添加到项目根目录,其中包含内容

set -e
use node
Run Code Online (Sandbox Code Playgroud)

最后 cd 到你的目录。(不要忘记来源 .zshenv)

direnv 会要求您允许加载配置。输入direnv allow瞧!

请注意,direnv 不支持lts/*.nvrmc 等花哨的结构。从积极的一面来看,direnv 支持一系列运行时,如 node、php、go、pyhton、ruby 等,允许我们使用单一工具来解决路径问题。

  • 谢谢,但我认为 MacOS 上默认不包含 direnv (2认同)

Liv*_*rce 6

现在有关于如何很好地做到这一点的官方文档,请参阅 deep-shell-integration https://github.com/nvm-sh/nvm#deeper-shell-integration