Node.js 命令行交互王者:inquirer 模块实战指南
在开发命令行工具时,我们常需要与用户互动 —— 比如让用户选择模板类型、输入项目名称、确认操作风险等。如果仅靠 process.argv
解析参数,不仅交互体验差,还无法应对复杂的选择场景。而 inquirer
模块的出现,彻底改变了 Node.js 命令行的交互方式,让我们能轻松构建出像 vue-cli
、create-react-app
那样流畅的交互式工具。
一、inquirer 模块的核心价值
inquirer
是目前 Node.js 生态中最主流的命令行交互库,每周下载量超 1000 万次,被众多知名工具采用。它的核心优势在于:
-
丰富的交互类型:支持输入框、单选、多选、确认、列表、密码等 8 种以上交互形式,覆盖几乎所有命令行交互场景。
-
灵活的配置项:可自定义验证规则、默认值、提示文案,甚至支持异步加载选项列表,满足个性化需求。
-
优雅的 UI 设计:自带清晰的视觉层级(如选中态、分隔线),支持彩色文字和加载动画,提升用户体验。
-
良好的兼容性:适配 Windows、macOS、Linux 等主流系统,同时支持 TypeScript 类型提示,降低开发成本。
-
轻量无冗余:核心依赖仅 2 个,安装包体积不足 50KB,不会给项目带来额外负担。
无论是开发脚手架、工程化脚本,还是运维工具,inquirer
都能让命令行交互从 “功能刚需” 升级为 “体验亮点”。
二、安装与基础使用
1. 安装模块
# 使用 npmnpm install inquirer# 使用 yarnyarn add inquirer# TypeScript 项目需额外安装类型定义npm install -D @types/inquirer
2. 第一个交互式示例
创建 cli.js
文件,实现一个简单的 “项目初始化” 交互流程:
import inquirer from \'inquirer\';// 定义交互问题列表const questions = [ // 1. 输入项目名称(带验证规则) { type: \"input\", // 交互类型:输入框 name: \"projectName\", // 结果存储的键名 message: \"请输入项目名称:\", default: \"my-project\", // 默认值 validate: (value) => { // 验证规则:只能包含小写字母和短横线 if (/^[a-z-]+$/.test(value)) { return true; // 验证通过 } return \"项目名称只能包含小写字母和短横线!\"; // 验证失败提示 }, }, // 2. 选择项目模板(单选) { type: \"list\", // 交互类型:列表(单选) name: \"template\", message: \"请选择项目模板:\", choices: [ // 选项列表 { name: \"Vue 3 模板\", value: \"vue3\" }, { name: \"React 模板\", value: \"react\" }, { name: \"Node.js 后端模板\", value: \"node\" }, ], }, // 3. 确认是否初始化 Git(确认框) { type: \"confirm\", // 交互类型:确认框(是/否) name: \"initGit\", message: \"是否初始化 Git 仓库?\", default: true, // 默认值:是 },];// 执行交互并处理结果inquirer.prompt(questions).then((answers) => { console.log(\"n===== 项目配置结果 =====\"); console.log(`项目名称:${answers.projectName}`); console.log(`选择模板:${answers.template}`); console.log(`初始化 Git:${answers.initGit ? \"是\" : \"否\"}`); console.log(\"n开始创建项目...\");});
运行脚本,即可看到交互式流程:
node cli.js
交互过程示例:
? 请输入项目名称: my-vue-app? 请选择项目模板: Vue 3 模板? 是否初始化 Git 仓库? Yes===== 项目配置结果 =====项目名称:my-vue-app选择模板:vue3初始化 Git:是开始创建项目...
三、核心交互类型与实战场景
inquirer
支持 10+ 种交互类型,以下是最常用的 6 种及对应的实战场景:
1. 输入框(input):处理文本输入
适用于需要用户输入自定义内容的场景(如项目名称、邮箱、URL):
{ type: \'input\', name: \'author\', message: \'请输入作者名称:\', default: \'匿名开发者\', // 输入时的提示(可选) transformer: (value) => `当前输入:${value}`, // 异步验证(如检查邮箱是否已注册) validate: async (value) => { // 模拟接口请求 await new Promise(resolve => setTimeout(resolve, 500)); if (value.includes(\'@\')) { return true; } return \'请输入有效的邮箱地址!\'; }}
2. 密码框(password):处理敏感信息
输入内容会被隐藏,适用于密码、密钥等敏感信息:
{ type: \'password\', name: \'dbPassword\', message: \'请输入数据库密码:\', // 可选:用 * 显示输入长度(默认完全隐藏) mask: \'*\'}
3. 单选列表(list):二选一或多选一
选项固定且需用户明确选择,适用于模板类型、环境选择等场景(如前文示例)。
4. 多选列表(checkbox):选择多个选项
支持用户勾选多个选项,适用于依赖安装、功能开启等场景:
{ type: \'checkbox\', name: \'features\', message: \'请选择需要集成的功能:\', choices: [ { name: \'TypeScript\', value: \'ts\', checked: true }, // 默认勾选 { name: \'ESLint\', value: \'eslint\' }, { name: \'Prettier\', value: \'prettier\' }, { name: \'单元测试\', value: \'test\' } ], // 限制最少选择 1 个 validate: (selected) => { if (selected.length >= 1) { return true; } return \'至少选择一个功能!\'; }}
交互结果会以数组形式返回,例如:features: [\'ts\', \'eslint\']
。
5. 下拉选择(rawlist):简化版单选
与 list
类似,但选项以编号展示,用户输入编号选择(更适合选项较多的场景):
{ type: \'rawlist\', name: \'framework\', message: \'请选择前端框架(输入编号):\', choices: [\'Vue\', \'React\', \'Angular\', \'Svelte\']}
交互示例:
? 请选择前端框架(输入编号): 1) Vue 2) React 3) Angular 4) Svelte> 2
6. 自动补全(autocomplete):智能输入提示
适用于选项较多且用户可能记不清完整名称的场景(如选择已有项目),需配合 inquirer-autocomplete-prompt
插件:
# 安装插件npm install inquirer-autocomplete-prompt
对应版本:
\"inquirer\": \"^9.1.0\",\"inquirer-autocomplete-prompt\": \"^3.0.1\"
import inquirer from \'inquirer\';import inquirerPrompt from \'inquirer-autocomplete-prompt\';// 注册自动补全插件inquirer.registerPrompt(\'autocomplete\', inquirerPrompt);// 模拟异步获取项目列表(如从数据库或接口获取)const searchProjects = async (answersSoFarm, input = \"\") => { const allProjects = [ \"project-admin\", \"project-user\", \"project-blog\", \"project-api\", ]; // 根据用户输入过滤结果 return allProjects.filter((project) => project.includes(input));};const questions = [ { type: \"autocomplete\", name: \"targetProject\", message: \"请选择要部署的项目(支持模糊搜索):\", source: searchProjects, // 异步获取选项的函数 },];inquirer.prompt(questions).then((answers) => { console.log(`已选择部署项目:${answers.targetProject}`);});
四、进阶技巧:提升交互体验
1. 条件性显示问题
根据用户之前的选择,动态显示或隐藏后续问题(如选择 “Vue 模板” 后才显示 Vue 版本选择):
const questions = [ { type: \"list\", name: \"template\", message: \"选择模板:\", choices: [\"vue\", \"react\", \"node\"], }, // 只有当 template 为 vue 时才显示该问题 { type: \"list\", name: \"vueVersion\", message: \"选择 Vue 版本:\", choices: [\"Vue 2\", \"Vue 3\"], when: (answers) => answers.template === \"vue\", // 条件判断 },];
2. 结合其他工具增强体验
搭配 chalk
(彩色文字)、ora
(加载动画)等工具,让交互流程更流畅:
# 安装依赖npm install chalk ora
import inquirer from \'inquirer\';import chalk from \'chalk\'import ora from \'ora\'const questions = [ { type: \"confirm\", name: \"deploy\", message: chalk.yellow(\"是否确认部署到生产环境?(此操作不可逆)\"), default: false, },];inquirer.prompt(questions).then(async (answers) => { if (answers.deploy) { // 显示加载动画 const spinner = ora(\"正在部署...\").start(); // 模拟部署耗时 await new Promise((resolve) => setTimeout(resolve, 2000)); spinner.succeed(chalk.green(\"部署成功!\")); } else { console.log(chalk.blue(\"已取消部署\")); }});
五、实战案例:构建简易脚手架
结合 inquirer
和 fs-extra
(文件操作工具),实现一个 “创建组件” 的脚手架:
# 安装依赖npm install inquirer fs-extra path
import inquirer from \'inquirer\';import fs from \'fs-extra\';import { fileURLToPath } from \'url\';import path from \'path\';const __filename = fileURLToPath(import.meta.url);const __dirname = path.dirname(__filename);// 组件模板内容const componentTemplate = (name) => ` <div class=\"${name}\"> <!-- ${name} 组件 -->
运行脚本后,只需按提示输入信息,即可快速创建符合规范的 Vue 组件,大幅提升开发效率。
六、总结
inquirer
以其丰富的交互类型、灵活的配置能力和优雅的 UI 设计,成为 Node.js 命令行工具的 “交互标配”。它不仅能满足基础的输入、选择需求,还能通过进阶技巧实现个性化、智能化的交互流程,让命令行工具从 “能用” 变为 “好用”。
如果你正在开发脚手架、工程化脚本或任何需要用户交互的命令行工具,inquirer
绝对是值得优先选择的工具。尝试用它重构你的脚本,你会发现命令行交互也能带来出色的用户体验!
欢迎在留言区分享你用 inquirer
开发的工具,或提出使用中遇到的问题,我们一起探讨更多交互技巧!