Node.js 命令行交互王者:inquirer 模块实战指南

在开发命令行工具时,我们常需要与用户互动 ------ 比如让用户选择模板类型、输入项目名称、确认操作风险等。如果仅靠 process.argv 解析参数,不仅交互体验差,还无法应对复杂的选择场景。而 inquirer 模块的出现,彻底改变了 Node.js 命令行的交互方式,让我们能轻松构建出像 vue-clicreate-react-app 那样流畅的交互式工具。

一、inquirer 模块的核心价值

inquirer 是目前 Node.js 生态中最主流的命令行交互库,每周下载量超 1000 万次,被众多知名工具采用。它的核心优势在于:

  • 丰富的交互类型:支持输入框、单选、多选、确认、列表、密码等 8 种以上交互形式,覆盖几乎所有命令行交互场景。

  • 灵活的配置项:可自定义验证规则、默认值、提示文案,甚至支持异步加载选项列表,满足个性化需求。

  • 优雅的 UI 设计:自带清晰的视觉层级(如选中态、分隔线),支持彩色文字和加载动画,提升用户体验。

  • 良好的兼容性:适配 Windows、macOS、Linux 等主流系统,同时支持 TypeScript 类型提示,降低开发成本。

  • 轻量无冗余:核心依赖仅 2 个,安装包体积不足 50KB,不会给项目带来额外负担。

无论是开发脚手架、工程化脚本,还是运维工具,inquirer 都能让命令行交互从 "功能刚需" 升级为 "体验亮点"。

二、安装与基础使用

1. 安装模块

shell 复制代码
# 使用 npm
npm install inquirer

# 使用 yarn
yarn add inquirer

# TypeScript 项目需额外安装类型定义
npm install -D @types/inquirer

2. 第一个交互式示例

创建 cli.js 文件,实现一个简单的 "项目初始化" 交互流程:

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开始创建项目...");
});

运行脚本,即可看到交互式流程:

shell 复制代码
node cli.js

交互过程示例:

shell 复制代码
? 请输入项目名称: my-vue-app

? 请选择项目模板: Vue 3 模板

? 是否初始化 Git 仓库? Yes

===== 项目配置结果 =====

项目名称:my-vue-app

选择模板:vue3

初始化 Git:是

开始创建项目...

三、核心交互类型与实战场景

inquirer 支持 10+ 种交互类型,以下是最常用的 6 种及对应的实战场景:

1. 输入框(input):处理文本输入

适用于需要用户输入自定义内容的场景(如项目名称、邮箱、URL):

js 复制代码
{
 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):处理敏感信息

输入内容会被隐藏,适用于密码、密钥等敏感信息:

js 复制代码
{
 type: 'password',
 name: 'dbPassword',
 message: '请输入数据库密码:',
 // 可选:用 * 显示输入长度(默认完全隐藏)
 mask: '*'
}

3. 单选列表(list):二选一或多选一

选项固定且需用户明确选择,适用于模板类型、环境选择等场景(如前文示例)。

4. 多选列表(checkbox):选择多个选项

支持用户勾选多个选项,适用于依赖安装、功能开启等场景:

js 复制代码
{
 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 类似,但选项以编号展示,用户输入编号选择(更适合选项较多的场景):

js 复制代码
{
 type: 'rawlist',
 name: 'framework',
 message: '请选择前端框架(输入编号):',
 choices: ['Vue', 'React', 'Angular', 'Svelte']
}

交互示例:

shell 复制代码
? 请选择前端框架(输入编号):

 1) Vue

 2) React

 3) Angular

 4) Svelte

> 2

6. 自动补全(autocomplete):智能输入提示

适用于选项较多且用户可能记不清完整名称的场景(如选择已有项目),需配合 inquirer-autocomplete-prompt 插件:

shell 复制代码
# 安装插件

npm install inquirer-autocomplete-prompt

对应版本:

json 复制代码
"inquirer": "^9.1.0",
"inquirer-autocomplete-prompt": "^3.0.1"
js 复制代码
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 版本选择):

js 复制代码
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(加载动画)等工具,让交互流程更流畅:

shell 复制代码
# 安装依赖
npm install chalk ora
js 复制代码
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("已取消部署"));
  }
});

五、实战案例:构建简易脚手架

结合 inquirerfs-extra(文件操作工具),实现一个 "创建组件" 的脚手架:

shell 复制代码
# 安装依赖
npm install inquirer fs-extra path
js 复制代码
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 开发的工具,或提出使用中遇到的问题,我们一起探讨更多交互技巧!

相关推荐
lay_liu19 分钟前
springboot 文件下载
java·spring boot·后端
2601_949816165 小时前
spring.profiles.active和spring.profiles.include的使用及区别说明
java·后端·spring
helx826 小时前
SpringBoot实战(三十二)集成 ofdrw,实现 PDF 和 OFD 的转换、SM2 签署OFD
spring boot·后端·pdf
rOuN STAT7 小时前
Skywalking介绍,Skywalking 9.4 安装,SpringBoot集成Skywalking
spring boot·后端·skywalking
吴声子夜歌7 小时前
Node.js——操作MySQL数据库
数据库·mysql·node.js
bilI LESS8 小时前
Spring Boot接收参数的19种方式
java·spring boot·后端
web前端进阶者9 小时前
Rust初学知识点快速记忆
开发语言·后端·rust
七夜zippoe9 小时前
API设计规范:RESTful API设计与OpenAPI(Swagger)完整指南
后端·restful·设计规范
2601_9498177210 小时前
Spring+SpringMVC项目中的容器初始化过程
java·后端·spring
青柠代码录10 小时前
【SpringBoot】集成 Knife4j
后端