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 .
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.