根据项目路径自动切换 node 版本
2024-06-13
最近被 node 版本切换搞烦了。我的 node 默认版本是 18,平时开发 umi4 项目是没问题的。当开发 umi3 的项目时,需要把 node 切换到 16 版本。当开发小程序时,又要把 node 切换到 21 版本...
于是想到了利用脚本自动切换 node 版本。网上搜了一下,解决方案大多是在项目根目录加一个.nvmrc
文件或者在package.json
中记录 node 版本,再通过脚本获取并切换。
这种方式能解决问题,不过我不希望在每个项目都加一个.nvmrc
。我理想的方式是:当我在某个项目中切换 node 版本时,用脚本记录下来。下次我进入这个项目的根目录时,脚本自动帮我切换到上次记录的版本。这种方式的好处是不用修改项目中的文件。实现原理有点类型zsh-z
插件,通过记录cd
过的目录来实现快速跳转。
我完全不会 shell 语法,所以脚本代码是让 AI 写的,不过代码并不能运行成功。经过修改后代码总算可以运行,代码如下:
#!/usr/bin/env zsh
# Set the data file path
data_file="$HOME/.nvm_auto_use/dirs"
# Create the data file if it doesn't exist
[[ -f $data_file ]] || { mkdir -p "${data_file:h}" && touch $data_file; }
# User-defined directory paths, can be set via environment variables, for example:
# export NVM_AUTO_USE_DIRS=( "/path/to/projects/dir1" "/path/to/projects/dir2" )
nvm_auto_use_dirs=( "${NVM_AUTO_USE_DIRS[@]:-$HOME}" )
# Associative array to store directory and nvm use command mappings
declare -A nvm_use_dirs
# Function to load data from the data file
function load_data() {
if [[ -f "$data_file" ]]; then
# Read data from the file
while read -r line; do
key=$(echo "$line" | cut -d'=' -f1)
value=$(echo "$line" | cut -d'=' -f2-)
nvm_use_dirs[$key]="$value"
done < "$data_file"
fi
}
# Function to save data to the data file
function save_data() {
# Clear the file content
echo "" > "$data_file" # Overwrite the file content using echo "" >
# Write the associative array to the file
for key in "${(k)nvm_use_dirs[@]}"; do
echo "$key=${nvm_use_dirs[$key]}" >> "$data_file"
done
}
# Function to check if the current directory is in the specified directory array
function is_in_nvm_auto_use_dirs() {
local current_dir="$PWD"
for dir in "${nvm_auto_use_dirs[@]}"; do
if [[ "$current_dir" == "$dir"/* ]]; then
return 0 # Current directory is within the specified directories
fi
done
return 1 # Current directory is not within the specified directories
}
# Function to handle the nvm use command
function nvm_use_handler() {
# Check if the current directory is in the array and the command is 'nvm use'
local cmd="$1"
if [[ "$cmd" =~ ^nvm\ use ]] && is_in_nvm_auto_use_dirs; then
local dir="$PWD"
nvm_use_dirs[$dir]="$cmd"
save_data # Save the data to the file
fi
}
# Function to automatically execute the nvm use command when entering a directory
function chpwd_handler() {
# Check if the current directory is in the specified directory array
if is_in_nvm_auto_use_dirs; then
local dir="$PWD"
if [[ -n "${nvm_use_dirs[$dir]}" ]]; then
eval "${nvm_use_dirs[$dir]}"
fi
fi
}
# Load saved data
load_data
# Register the nvm use command handler
autoload -Uz add-zsh-hook
add-zsh-hook preexec nvm_use_handler
# Register the chpwd hook function
add-zsh-hook chpwd chpwd_handler
在 ~/.zshrc
中 source
一下就能运行。
代码仓库在这里。
配合 zsh-z 插件实现一个命令快速启动项目
可以在 ~/.zshrc
中加入两个函数
# Open a frontend project immediately
function zo(){
z "$1"
code .
}
# Start a frontend project immediately
function zs(){
z "$1"
code .
yarn start
}
zs
函数可以让我们快速用 vscode 打开该项目并且启动该项目,配合上面的 node 版本切换,我 90% 的前端项目都可以通过这个函数快速打开。有些项目不是用 yarn 管理的,这里可以优化一下,通过 lock 文件判断是使用哪个包管理工具,或者使用 ni。不过写死 yarn 对我来说已经够了。
有时候希望打开项目前,先切换分支或者同步最新代码,此时可以使用 zo
函数,只用 vscode 打开项目而不启动它,手动切换好分支后再启动项目。