jalankan `nvm use` secara otomatis setiap kali ada file .nvmrc di direktori

87

Bagaimana cara mengkonfigurasi shell saya agar nvm useberjalan secara otomatis setiap kali ada file .nvmrc di direktori dan menggunakan versi terbaru atau konfigurasi global ketika tidak ada file .nvmrc?

Gabo Esquivel
sumber
2
Kasus penggunaan ini sekarang didokumentasikan dalam dokumentasi resmi nvm di bawah Integrasi Deep Shell . Anda juga dapat melihat jawaban saya untuk bashcangkangnya.
d4nyll

Jawaban:

89

Jika Anda menggunakan zsh (z shell):

Memanggil 'nvm use' secara otomatis dalam direktori dengan file .nvmrc

Masukkan ini ke dalam $ HOME / .zshrc Anda untuk memanggil penggunaan nvm secara otomatis setiap kali Anda memasuki direktori yang berisi file .nvmrc dengan string yang memberi tahu nvm node mana yang akan digunakan:

# 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

Info lebih lanjut: https://github.com/creationix/nvm#zsh

Rotareti
sumber
6
Ini bekerja dengan sangat baik bagi saya, tetapi menyebabkan penurunan kinerja cd, karena berjalan setiap kali Anda mengubah direktori. Saya menambahkan [[ -a .nvmrc ]] || returnke baris pertama load-nvmrc (), dan itu secara signifikan meningkatkan kinerjanya
Belgabad
1
@Belgabad Ini lebih berkinerja, karena dengan baris Anda, skrip tidak akan memeriksa .nvmrcdi direktori induk dan juga tidak akan kembali ke nodeversi default saat Anda cdkeluar dari direktori proyek.
Rotareti
50

Jika Anda menggunakan bash, Anda dapat menambahkan ini ke ~/.bashrcfile Anda :

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

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

export PROMPT_COMMAND=enter_directory
devius
sumber
32

Jawaban luar biasa dari @devius .

Saya baru saja memperpanjangnya sehingga dapat kembali ke versi default ketika meninggalkan direktori dengan yang .nvmrclain tanpa itu.

~/.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
sumber
Menggunakan bash di windows, ini mengembalikan node v.0.0 (64-bit) is not installed.meskipun file .nvmrc memiliki 9.3.
hofnarwillie
2
Diperbaiki dengan menggunakanVERSION=$(cat .nvmrc); nvm use $VERSION
hofnarwillie
Saya juga harus mengatakan itu menggunakan nvm-for-windows yang merupakan binatang yang sama sekali berbeda. Tetapi dengan skrip + modifikasi di atas, ia bekerja dengan baik. +1
hofnarwillie
26

Saya baru tahu tentang Pengalihan Versi Otomatis untuk Node.js https://github.com/wbyoung/avn , Anda dapat menggunakannya.

Anda juga dapat mengikuti utas ini https://github.com/creationix/nvm/issues/110

Gabo Esquivel
sumber
32
Ini menyedihkan .. apakah tidak ada batasan untuk kedalaman tumpukan alat? node → npm → nvm → avn, dan backup. mendesah saya akan bermain bola, tapi gairah saya memudar dengan setiap hack. (dan terima kasih untuk tautannya, tentu saja, gabo.)
hraban
Tak satu pun komentar di utas yang disebutkan berfungsi dengan bash untuk saya. Mungkin semuanya untuk MacOS. Untuk sesuatu yang berfungsi di Ubuntu, periksa jawaban saya di bawah ini.
devius
15

Jawaban ini diambil dari dokumentasi resmi nvm .

Letakkan yang berikut ini di akhir Anda $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'

Ini merupakan peningkatan dari:

Alias ​​ini akan mencari 'up' dari direktori Anda saat ini untuk mendeteksi .nvmrcfile. Jika menemukannya, itu akan beralih ke versi itu; jika tidak, itu akan menggunakan versi default.

d4nyll
sumber
Muncul sedikit lambat tapi saya sangat suka opsi ini
BossmanT
@BossmanT Dengan 'tampak agak lambat', apakah maksud Anda Anda akan menebak itu lambat dari melihat apa yang dilakukannya, atau Anda benar-benar merasa lambat untuk dijalankan?
callum
@callum hanya dari mengamatinya berjalan di lingkungan bash saya, tidak ada uji coba waktu yang dijalankan untuk itu, bagaimanapun, ini tentang sepersekian detik lebih lambat, tidak ada yang signifikan tentu saja
BossmanT
Saya tidak bisa mendeteksi adanya kelambatan. Berlari cdbukanlah sesuatu yang mungkin Anda lakukan dalam jumlah besar, jadi menurut saya itu tidak penting kecuali jika kelambatannya terlihat oleh manusia.
callum
3

Saya mencoba banyak solusi untuk ini dan tidak ada yang berhasil seperti yang saya inginkan, jadi saya menulis sendiri:

Fungsi ZSH untuk beralih otomatis ke versi node yang benar

Sejauh yang saya tahu, ini adalah satu-satunya yang memenuhi semua kriteria berikut:

  • menjamin Anda selalu menggunakan versi yang benar dengan mencari pohon direktori untuk menemukan yang terdekat .nvmrc(seperti nvm use);
  • dapat menangani .nvmrcformat apa pun yang valid ;
  • dengan jelas memperingatkan Anda jika tidak ada versi terinstal yang memenuhi .nvmrc,
  • mengasumsikan Anda ingin defaultjika tidak ada .nvmrctempat di atas pohon;
  • benar-benar sunyi dan cepat jika Anda sudah menggunakan versi Node yang benar.
callum
sumber
1

Namun solusi lain menggunakan direnv . Direnv hadir dengan OS X dan banyak distro sehingga tidak diperlukan instalasi.

Tambahkan dua baris ini ke .zshenv atau .bash_profile Anda tergantung pada shell yang Anda gunakan:


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

Tambahkan file .envrc ke root proyek dengan isinya

set -e
use node

Terakhir, cd ke direktori Anda. (Jangan lupa untuk mencari .zshenv)

direnv akan meminta Anda untuk mengizinkan konfigurasi beban. Ketik direnv allowdan voila!

Perhatikan bahwa direnv tidak mendukung konstruksi mewah seperti lts/*di .nvrmc. Sisi positifnya, direnv mendukung banyak runtime seperti node, php, go, pyhton, ruby, dll. Memungkinkan kita menggunakan satu alat untuk memecahkan masalah jalur.

R. Haluk Öngör
sumber
0

Memperluas jawaban @Adriano P , saya akan mengusulkan versi ini yang kurang umum (hanya berfungsi jika .nvmrcdisetel pada root repositori git ), tetapi berfungsi jika kita menavigasi ke tempat lain dalam proyek selain akarnya:

_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
sumber
0

Saya menggunakan kerangka konfigurasi zsh ini yang disebut Oh My Zsh. Ini adalah repositori yang sangat aktif dengan pembaruan rutin. Cobalah dan saya yakin Anda akan menyukainya. Oh, dan ia memiliki fitur otomatis .nvmrc bawaan sehingga semudah menginstal paket melalui npm!

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

Satya Sampathirao
sumber