ejecute `nvm use` automáticamente cada vez que haya un archivo .nvmrc en el directorio

87

¿Cómo configurar mi shell para que se nvm useejecute automáticamente cada vez que haya un archivo .nvmrc en el directorio y use la última versión o una configuración global cuando no haya un archivo .nvmrc?

Gabo Esquivel
fuente
2
Este caso de uso ahora está documentado en la documentación oficial de nvm en Deep Shell Integration . También puede ver mi respuesta para el bashshell.
d4nyll

Respuestas:

86

Si usa zsh (z shell):

Llamar a 'nvm use' automáticamente en un directorio con un archivo .nvmrc

Ponga esto en su $ HOME / .zshrc para llamar a nvm use automáticamente cada vez que ingrese a un directorio que contenga un archivo .nvmrc con una cadena que indique a nvm qué nodo usar:

# 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

Más información: https://github.com/creationix/nvm#zsh

Rotareti
fuente
5
Esto funcionó muy bien para mí, pero causó un impacto en el rendimiento cd, ya que se ejecuta cada vez que cambia de directorio. Añadí [[ -a .nvmrc ]] || returna la primera línea de carga-nvmrc (), y que la mejora significativamente el rendimiento de la misma
Belgabad
@Belgabad Es más eficaz, porque con su línea el script no buscará .nvmrcen los directorios principales y tampoco volverá a la nodeversión predeterminada cuando cdsalga del directorio del proyecto.
Rotareti
49

Si usa bash , puede agregar esto a su ~/.bashrcarchivo:

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

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

export PROMPT_COMMAND=enter_directory
devius
fuente
30

Excelente respuesta de @devius .

Simplemente lo extendí para que pueda volver a la versión predeterminada al dejar un directorio con .nvmrcotro sin él.

~/.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
Adriano P
fuente
Al usar bash en Windows, esto devuelve node v.0.0 (64-bit) is not installed.aunque el archivo .nvmrc tenga 9.3.
hofnarwillie
2
Se VERSION=$(cat .nvmrc); nvm use $VERSION
corrigió
También debo decir que está usando nvm-for-windows, que es una bestia completamente diferente. Pero con el script anterior + modificación funciona de maravilla. +1
hofnarwillie
26

Me acabo de enterar del cambio automático de versión para Node.js https://github.com/wbyoung/avn , puedes usar eso.

También puede seguir este hilo https://github.com/creationix/nvm/issues/110

Gabo Esquivel
fuente
28
Esto es deprimente ... ¿no hay límite para la profundidad de la pila de herramientas? nodo → npm → nvm → avn, y haga una copia de seguridad. Suspiro voy a jugar a la pelota, pero mi pasión está menguando con cada truco. (y gracias por el enlace, por supuesto, gabo.)
hraban
Ninguno de los comentarios en el hilo mencionado funcionó con bash para mí. Quizás todos sean para MacOS. Para algo que funcione en Ubuntu, verifique mi respuesta a continuación.
devius
12

Esta respuesta se toma de la documentación oficial de nvm .

Pon lo siguiente al final de tu $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'

Esta es una mejora con respecto a:

Este alias buscaría 'arriba' en su directorio actual para detectar un .nvmrcarchivo. Si lo encuentra, cambiará a esa versión; si no, usará la versión predeterminada.

d4nyll
fuente
Parece un poco lento, pero realmente me gusta esta opción
BossmanT
@BossmanT Por 'parece un poco lento', ¿quiere decir que adivinaría que es lento al ver lo que hace, o que en realidad lo encontró lento para ejecutar?
callum
@callum solo por observarlo funcionando en mi entorno de bash, sin embargo, no se realizaron pruebas de tiempo, es aproximadamente una fracción de segundo más lento, no es nada significativo, por supuesto
BossmanT
No pude detectar ningún retraso. Correr cdno es algo que puedas hacer en grandes lotes, así que no creo que importe a menos que el retraso sea perceptible para un humano.
callum
2

Probé muchas soluciones para esto y nada funcionó como quería, así que escribí la mía propia:

Función ZSH para cambiar automáticamente a la versión correcta del nodo

Hasta donde yo sé, este es el único que cumple con todos los siguientes criterios:

  • garantiza que siempre está en la versión correcta al buscar en el árbol de directorios para encontrar la más cercana .nvmrc(como nvm use);
  • puede manejar cualquier .nvmrcformato válido ;
  • le advierte claramente si ninguna versión instalada satisface el .nvmrc,
  • asume que quieres defaultsi no hay ningún .nvmrclugar en el árbol;
  • es completamente silencioso y rápido si ya está en la versión correcta de Node.
callum
fuente
1

Otra solución más usando direnv . Direnv viene con OS X y muchas distribuciones, por lo que no se necesita instalación.

Agregue estas dos líneas a su .zshenv o .bash_profile según el shell que use:


export NVM_DIR="$HOME/.nvm" # You probably have this line already
export NODE_VERSIONS="${NVM_DIR}/versions/node"
export NODE_VERSION_PREFIX="v"

Agregue un archivo .envrc a la raíz del proyecto con el contenido

set -e
use node

Finalmente, vaya a su directorio. (No se olvide de la fuente .zshenv)

direnv le pedirá que permita la configuración de carga. Escribe direnv allowy listo!

Tenga en cuenta que direnv no admite construcciones sofisticadas como lts/*en .nvrmc. En el lado positivo, direnv admite varios tiempos de ejecución como node, php, go, pyhton, ruby, etc., lo que nos permite usar una sola herramienta para resolver problemas de ruta.

R. Haluk Öngör
fuente
0

Ampliando la respuesta de @Adriano P , propondría esta versión que es menos general (solo funciona si .nvmrcestá configurada en una raíz de repositorio de git ), pero funciona en los casos en que navegamos a otra parte del proyecto que no sea su raíz:

_enter_dir() {
    local git_root
    git_root=$(git rev-parse --show-toplevel 2>/dev/null)

    if [[ "$git_root" == "$PREV_PWD" ]]; then
        return
    elif [[ -n "$git_root" && -f "$git_root/.nvmrc" ]]; then
        nvm use
        NVM_DIRTY=1
    elif [[ "$NVM_DIRTY" == 1 ]]; then
        nvm use default
        NVM_DIRTY=0
    fi
    PREV_PWD="$git_root"
}

export PROMPT_COMMAND=_enter_dir
#export PROMPT_COMMAND="$PROMPT_COMMAND;_enter_dir"  # use this if PROMPT_COMMAND already defined
laur
fuente
0

Utilizo este marco de configuración de zsh llamado Oh My Zsh. Es un repositorio muy activo con actualizaciones periódicas. Pruébalo y seguro que te encantará. ¡Ah, y tiene la función automática .nvmrc incorporada, por lo que es tan simple como instalar el paquete a través de npm!

https://github.com/robbyrussell/oh-my-zsh

Satya Sampathirao
fuente