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. 安装模块
# 使用 npm
npm install inquirer# 使用 yarn
yarn 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) Vue2) React3) Angular4) 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) => `
<template><div class="${name}"><!-- ${name} 组件 --></div>
</template><script setup>
// 组件逻辑
</script><style scoped>
.${name} {/* 样式 */
}
</style>
`;// 交互流程
const createComponent = async () => {const questions = [{type: "input",name: "componentName",message: "请输入组件名称( PascalCase 格式):",default: "MyComponent",validate: (value) => {if (/^[A-Z][a-zA-Z0-9]*$/.test(value)) {return true;}return "请输入 PascalCase 格式的名称(如 Button、UserCard)";},},{type: "list",name: "componentType",message: "选择组件类型:",choices: ["页面组件", "公共组件"],filter: (value) => (value === "页面组件" ? "views" : "components"), // 转换值},];// 执行交互const answers = await inquirer.prompt(questions);const { componentName, componentType } = answers;const dir = path.resolve(__dirname,`./src/${componentType}`);// 组件保存路径const componentPath = path.join(dir,`${componentName}.vue`);await fs.ensureDir(dir);// 检查组件是否已存在if (await fs.pathExists(componentPath)) {console.log(`❌ 组件 ${componentName} 已存在`);return;}// 写入组件文件await fs.writeFile(componentPath, componentTemplate(componentName));console.log(`✅ 组件 ${componentName} 创建成功,路径:${componentPath}`);
};// 启动脚手架
createComponent();
运行脚本后,只需按提示输入信息,即可快速创建符合规范的 Vue 组件,大幅提升开发效率。
六、总结
inquirer
以其丰富的交互类型、灵活的配置能力和优雅的 UI 设计,成为 Node.js 命令行工具的 “交互标配”。它不仅能满足基础的输入、选择需求,还能通过进阶技巧实现个性化、智能化的交互流程,让命令行工具从 “能用” 变为 “好用”。
如果你正在开发脚手架、工程化脚本或任何需要用户交互的命令行工具,inquirer
绝对是值得优先选择的工具。尝试用它重构你的脚本,你会发现命令行交互也能带来出色的用户体验!
欢迎在留言区分享你用 inquirer
开发的工具,或提出使用中遇到的问题,我们一起探讨更多交互技巧!