使用Node.js fs模块与yargs开发CLI时If/Else If分支未触发问题
核心问题排查
这里列出你代码中存在的3个直接导致报错的缺陷:
- 逻辑分支顺序错误,空值传入文件操作API
你当前的判断逻辑是componentName !== undefined时执行创建,否则才走存在性判断分支。这意味着触发存在性判断时componentName一定是undefined,拼接出的路径会变成./src/components/undefined,属于非法路径会直接触发报错。
同时你的重复校验逻辑完全没有覆盖创建分支,组件创建前不会做重复判断,目标目录已存在时fs.mkdirSync会直接抛出EEXIST类型错误。 - 参数定义类型错误,无法拿到用户输入的组件名
你把componentName定义为options类型参数,需要用户加--componentName前缀才能传值。但你命令说明里的用法vcli component title中的title属于位置参数,需要用positional方法定义而非options,所以正常执行命令时你根本拿不到用户输入的组件名,componentName始终为undefined。 - 路径与目录创建逻辑缺陷
你用了相对路径./src/components,这个路径是相对于用户执行命令的工作目录,若用户不在项目根目录执行命令,会因为父目录不存在导致mkdirSync抛出ENOENT错误。同时mkdirSync默认不会递归创建父目录,若项目中还没创建src/components目录也会直接报错。
修复后代码
import type { Arguments, CommandBuilder } from 'yargs'; import chalk from 'chalk'; import * as logos from '../logos'; import fs from 'fs'; import path from 'path'; type Options = { componentName?: string; }; // 声明位置参数componentName export const command: string[] = ["component [componentName]", "c", "comp"]; export const desc: string = 'Creates a component. Use: "vcli component title" - this makes a new title component (optional).'; export const builder: CommandBuilder<Options, Options> = (yargs) => yargs // 用positional定义位置参数 .positional('componentName', { type: 'string', description: 'Name of the component to create' }); export const handler = (argv: Arguments<Options>): void => { const { componentName } = argv; // 优先处理无参数场景,预留交互逻辑位置 if (!componentName) { // 后续这里写inquirer.js交互逻辑 console.log(chalk.yellow(`${logos.prefix} Please enter component name`)); return; } // 拼接绝对路径,不受执行工作目录影响 const componentDir = path.resolve(process.cwd(), 'src/components', componentName); // 先做重复校验 if (fs.existsSync(componentDir)) { console.log(chalk.red(`${logos.prefix} Component ${componentName} already exists!`)); return; } const timerMsg: string = `${logos.prefix} Component with name '${componentName}' has been successfully created in` console.time(chalk.green(timerMsg)); // 加recursive参数自动创建不存在的父目录 fs.mkdirSync(componentDir, { recursive: true }); fs.writeFileSync(path.join(componentDir, 'index.tsx'), `import React from 'react';\n\nimport './${componentName}Styles.scss'`); console.timeEnd(chalk.green(timerMsg)); };
内容的提问来源于stack exchange,提问作者Psuedodoro
相关产品推荐
相关产品推荐

