前言
哈喽大家好!我是嘟老板 ,由于手上负责好几个项目,新老不一,基本上每次开发前都要切换 node
版本,以保证项目正常启动,但凡一不留神忘记了,就会白白浪费几分钟时间,本来是坐等服务启动,结果迎来了一大堆报错。为了彻底解决这类问题,我特地开发了一个 vscode 插件 - auto-nvm,再也不用担心忘记切换了,真香。
阅读本文您将收获:
- auto-nvm 设计背景、思路及实现过程。
- auto-nvm 插件完整开发过程。
- 等等...
why auto-nvm
背景
其实标题已经说的很清楚了,目前负责了太多的前端项目,有老有新,每次交替开发时,都要先切换 node
版本,不然就分分钟报错给你看。
现在"年纪大了",不想频繁的手动切换版本,更不想经过漫长的等待,因 node
版本导致服务启动失败,就想着能不能每次打开项目自动切换 node
版本。
由于一直以来都在用 nvm
管理 node
环境,所以就从 nvm
入手,借助 nvm
的能力实现自动切换。
规划
目前没打算做的太复杂,大致规划以下两点:
- (核心)打开前端项目自动切换 node 版本。
- 提供 Use Node Version 命令,支持手动切换
node
版本。
截至发文,
auto-nvm
已迭代几个版本,功能更完善,欢迎使用。
开发流程
初始化项目
使用 Yeoman 和 vscode 插件生成器 工具初始化插件工程。
终端输入以下命令,回车执行:
bash
npm install --global yo generator-code
yo code
问答环节结束后即可完成创建。
初始工程目录结构如下。
清除 src/extension.ts 中无用代码及注释,精简如下:
javascript
import * as vscode from "vscode";
export function activate(context: vscode.ExtensionContext) {
console.log('auto-nvm is now active');
}
export function deactivate() {}
(核心)自动切换 node 版本
设计思路
- 若想实现自动切换,首先要明确每个项目所需的
node
版本,那怎么才能知道需要哪个版本呢?答案是配置文件 ,恰好nvm
支持 .nvmrc,帮我们省去了读取配置的过程。 - 在 .nvmrc 中配置
node
版本,如v18.12.0
,执行nvm use
命令后,会切换版本至v18.12.0
。 auto-nvm
插件激活后,自动在每个打开的终端执行nvm use
命令,即可切换。
上代码
executeNvmUse 工具函数
创建一个 executeNvmUse
工具函数,用来在 vscode 终端执行 nvm use
命令。
js
/**
* 终端 t 发送 nvm use
*/
function sendNvmUserText(t: vscode.Terminal) {
t.sendText("nvm use");
}
/**
* 为 vscode 每个打开的终端执行 "nvm use",切换 node 版本
*/
export function executeNvmUse() {
// 获取打开的终端列表
const terminals = vscode.window.terminals;
if (terminals.length) {
terminals.forEach(sendNvmUserText);
}
// 监听终端创建事件,创建终端后首先切换 node 版本
vscode.window.onDidOpenTerminal(sendNvmUserText);
}
调用 executeNvmUse
在 src/extension.ts
中引入 executeNvmUse
函数,并在 activate 函数内调用,表示插件激活后执行 nvm use
。
js
import * as vscode from "vscode";
import { executeNvmUse } from "./utils";
export function activate(context: vscode.ExtensionContext) {
console.log('extension "auto-nvm" is now active!');
executeNvmUse();
}
操作演示
到这基本的自动切换功能就完活了,快捷键 F5 测试一下。
在新窗口中打开一个测试项目,新增 .nvmrc
配置文件并写入 v18
。
新建终端,发现自动执行了 nvm use
命令,并且切换了 node 版本。
OK,符合预期。
Use Node Version 命令
提供一个 Use Node Version 命令,允许手动切换 node
版本。
设计思路
若用户本地环境没有安装 .nvmrc
配置的 node
版本,则自动切换会失败,这就需要用户手动操作切换。
- crtl+shift+p(window) 或 cmd+shift+p(mac) 搜索 Use Node Version 命令回车执行
- 弹出输入框允许用户输入版本号。
- 回车确认并切换,终端自动执行
nvm use [version]
。
截至发文,
Use Node Version
功能已更新,会自动获取用户本地已安装的 node 版本,供选择,无需手动输入;且提供安装其他版本入口,供用户按需安装。
操作流程如下:
上代码
src 目录下新增 register-command 文件,专门用于维护命令注册函数。
创建 registerUseVersionCommand 函数,编写注册 use-version 命令的代码。
js
import * as vscode from "vscode";
import { executeNvmUse } from "./utils";
// 匹配 nvm use 可用的 node 版本写法
const nvmNodeVersionRegexp = /^(v)?(0|[1-9]\d{0,1})(\.(0|[1-9]\d*)){0,2}$/;
/**
* 注册 use-version 命令
*/
export function registerUseVersionCommand(context: vscode.ExtensionContext) {
const commandId = "auto-nvm.use-version";
const commandHandler = () => {
// 显示输入框
vscode.window
.showInputBox({
prompt: "enter the node version", // 输入框的提示信息
placeHolder: "eg. 20, v20, 20.11.0, v20.11.0", // 输入框的占位符
validateInput: (version) => {
// 验证输入的函数
if (!nvmNodeVersionRegexp.test(version)) {
return "invalid version";
}
return null;
},
})
.then((version) => {
if (version) {
executeNvmUse(version);
vscode.window.showInformationMessage(
`"nvm use ${version}" command has been sent, please check terminals`
);
}
});
};
context.subscriptions.push(
vscode.commands.registerCommand(commandId, commandHandler)
);
}
注册命令的核心是 vscode.commands.registerCommand(commandId, commandHandler)
这行代码,表示注册一个 ID
为 auto-nvm.use-version ,处理函数为 commandHandler 的命令。
commandHandler 定义了 use-version
的具体行为,当 crtl+shift+p(window) 或 cmd+shift+p(mac) 执行 Use Node Version
命令时,会调用 showInputBox api 弹出一个输入框,供用户输入要切换的 node 版本号,如 20、v20 等;输入过程中,会执行 validateInput 配置的校验函数,以保障用户输入的准确性;用户回车确认后,会调用 executeNvmUse 函数,以在控制台执行 nvm use ${version}
命令,切换 node 版本;最后右下角弹窗提示。
跟着操作的小伙伴可能会发现,咦?executeNvmUse
函数怎么可以传参数了,哈哈,当然是调整过啦,以下是调整后的相关代码:
js
/**
* 终端 t 发送 nvm use
*/
function sendNvmUseText(t: vscode.Terminal, version: string | null = "") {
t.sendText(`nvm use ${version}`);
}
/**
* 为 vscode 每个打开的终端执行 "nvm use",切换 node 版本
*/
export function executeNvmUse(version?: string) {
// 获取打开的终端列表
const terminals = vscode.window.terminals;
if (terminals.length) {
terminals.forEach((t) => sendNvmUseText(t, version));
}
}
/**
* 插件 active 时初始执行
*/
export function initNvmUse(context: vscode.ExtensionContext) {
// 为 vscode 每个打开的终端执行 "nvm use"
executeNvmUse();
// 监听终端创建事件,创建终端后首先切换 node 版本
context.subscriptions.push(vscode.window.onDidOpenTerminal(sendNvmUseText));
}
executeNvmUse 函数改为纯粹的在终端中执行 nvm use
,接受 version
参数,用于指定 use 的 node 版本。
新增一个 initNvmUse 函数,用于在 extension.ts
中的 activate 函数内调用。
activate 函数调整如下:
js
import * as vscode from "vscode";
import { initNvmUse } from "./utils";
import { registerUseVersionCommand } from "./register-commands";
export function activate(context: vscode.ExtensionContext) {
console.log("auto-nvm is now active!");
initNvmUse(context);
registerUseVersionCommand(context);
}
最后一步,在 package.json
中配置 contributes.commands
,以使 Use Node Version
命令在 vscode 的命令面板中可用:
json
{
"contributes": {
"commands": [
{
"command": "auto-nvm.use-version",
"title": "Use Node Version",
"description": "use specified version"
}
]
},
}
操作演示
代码到此告一段落,来看下演示效果:
小优化
现在插件仅会在执行 Use Node Version 命令时激活插件,而 vscode
编辑器打开后通常会有未关闭的终端窗口,这就导致执行 Use Node Version 前,原有的终端窗口不会切换 node
版本。
解决方法也比较简单,在 package.json 中配置 activationEvents 即可,默认为空数组,即执行命令时激活。
若想任意条件都激活插件,可以配置一个包含 星号(*)
的数组。
json
"activationEvents": ["*"],
不过通常不建议这么配置,会影响 vscode 性能,需要限制一下,比如 auto-nvm 配置如下,在 vscode 启动完成后激活。
json
"activationEvents": [ "onStartupFinished", "workspaceContains:.nvmrc" ],
完活!!!
结语
本文重点介绍了 auto-nvm 整个设计及大致开发过程,旨在帮助同学们加深对于 auto-nvm 特性的理解。如有需要,欢迎安装,反馈,万分感谢!
如您对文章内容有任何疑问或想深入讨论,欢迎评论区留下您的问题和见解。
技术简而不凡,创新生生不息。我是 嘟老板,咱们下期再会。
往期干货
- TypeORM 知多少?来看看 Node 服务端如何基于 TypeORM 封装 BaseService
- 还在考虑 node 服务端如何管理环境变量?来试试 node-config
- 还在纠结 node 服务端缓存怎么做?来试试 Redis
- 听说过 BEM 吗?聊聊如何落地 BEM 规范
- 还在好奇 node 后端登录流程怎么做?进来聊聊吧
- 借助 CSS 动画,撸一个"平平无奇"的登录页
- express 基础入门
- 搞定 TS 装饰器,让你写 Node 接口更轻松
- 一文带你了解多数企业系统都在用的 RBAC 权限管理策略
- 还不会搭建 Node 服务?一文带你了解如何用 express + ts 搞定后端