Automatic Node.js Version Switching Plugin for VS Code
This article explains the limitations of global Node version managers like n and nvm, presents a demo Node script for per‑project version switching, and details a VS Code extension that automatically detects a project's required Node version and switches it in the integrated terminal.
Background
I was learning Next.js, which requires Node ≥ v18.17.0, while an older company project is limited to Node ≤ v16.20.0, so I used v16.20.0 at work and v20.0.0 after hours. Forgetting to switch versions with n caused frequent errors, prompting me to create a plugin that automatically switches Node versions per project.
n and nvm implementation principles
n implementation
n stores all Node versions under /usr/local/n/versions , each in a subdirectory named after the version.
Switching copies the selected version's /usr/local/n/versions/{version}/bin/node binary to /usr/local/bin , making the change global.
Therefore, n switches versions globally and cannot be configured per directory.
nvm implementation
When installing a specific Node version, nvm downloads the pre‑compiled binary and extracts it to ~/.nvm/versions/node/{version} , keeping each version isolated.
Running nvm use <version> prepends the selected version's bin directory to the PATH environment variable, so subsequent node or npm commands use that version.
To load nvm in new shell sessions, users add a source ~/.nvm/nvm.sh line to their ~/.bashrc or ~/.zshrc files.
Thus, nvm allows independent Node versions per shell session.
Node script
Implementation idea
Read the nodeVersion field from the project's package.json; if present, invoke n to switch to that version before starting the project.
Demo code
const { spawn } = require('child_process');
const { readFileSync } = require('fs');
const path = require('path');
const { cwd } = require('process');
let packageJson = readFileSync(path.join(cwd(), '/package.json')).toString();
if (packageJson) {
packageJson = JSON.parse(packageJson);
}
if (packageJson.nodeVersion) {
// Execute n command
spawn('n', [packageJson.nodeVersion]);
}The demo reads nodeVersion from package.json and runs n to switch versions.
VS Code plugin
Implementation idea
Because projects are usually started from VS Code's integrated terminal, the plugin detects the opened terminal, reads the project's nodeVersion, and sends the appropriate nvm use command to the terminal without affecting other projects.
Implementation steps
Create VS Code extension project
npm install -g yo
yo codeCore code (extension.js)
// extension.js
const { existsSync, readFileSync } = require('fs');
const { join } = require('path');
const vscode = require('vscode');
const { exec } = require('child_process');
function commandExistsInShell(shell, command, callback) {
let execCommand = `type ${command}`;
if (shell.includes('zsh')) {
execCommand = `source ~/.zshrc && type ${command}`;
}
exec(execCommand, { shell }, (error, stdout, stderr) => {
if (error || stderr) return callback(false);
callback(true);
});
}
function activate() {
vscode.window.onDidOpenTerminal((terminal) => {
if (!vscode.workspace.workspaceFolders) return;
const workspacePath = vscode.workspace.workspaceFolders[0].uri.fsPath;
const pkgPath = join(workspacePath, '/package.json');
if (!existsSync(pkgPath)) return;
const pkgStr = readFileSync(pkgPath, 'utf8').toString();
if (!pkgStr) return;
try {
const pkg = JSON.parse(pkgStr);
if (!pkg.nodeVersion) return;
const { shellPath } = terminal.creationOptions;
commandExistsInShell(shellPath, 'nvm', (exists) => {
if (exists) {
let command = `source ~/.nvm/nvm.sh && nvm ls ${pkg.nodeVersion}`;
if (shellPath.includes('fish')) command = `nvm ls ${pkg.nodeVersion}`;
exec(command, { shell: shellPath }, (error, stdout, stderr) => {
if (error || stderr) {
vscode.window.showErrorMessage(`${pkg.nodeVersion} version not found, install?`, 'Yes', 'No')
.then((value) => {
if (value === 'Yes') terminal.sendText(`nvm install ${pkg.nodeVersion}`, true);
});
return;
}
if (stdout) {
terminal.sendText('nvm use ' + pkg.nodeVersion, true);
}
});
} else {
vscode.window.showErrorMessage('nvm command not found, install it first.', 'View guide', 'Cancel')
.then((value) => {
if (value === 'View guide') vscode.env.openExternal(vscode.Uri.parse('https://github.com/nvm-sh/nvm'));
});
}
});
} catch (e) {}
});
}
function deactivate() {}
module.exports = { activate, deactivate };Demo effect
Conclusion
The extension has been published to the VS Code Marketplace (search for auto-switch-node-version or visit the provided link). Users must install nvm first; installation instructions are linked. Source code is available at GitHub .
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
