当前位置: 首页 > 科技观察

从零开始开发一个node命令行工具

时间:2023-03-15 15:43:50 科技观察

什么是命令行工具?命令行工具(CmmandLineInterface)简称cli。顾名思义,它是一个在命令行终端中使用的工具。我们常用的git、npm、vim等都是cli工具。比如我们可以简单的通过gitclone等命令将远程代码复制到本地。为什么要使用cli工具?与cli相对的是图形用户界面(gui)。在windows环境下,几乎都是gui工具,而在linux环境下,几乎都是cli工具。因为两者的使用者不同,gui侧重于易用性,而cli侧重于效率。对于熟悉GUI和集成开发环境(IDE)的程序员来说,这似乎很难理解。毕竟用鼠标点击拖动不是更方便吗?不幸的是,答案是否定的。GUI对于一些简单的操作可能会更快更方便。例如移动文件、阅读电子邮件或编写word文档。但是,如果您对所有事情都依赖于图形用户界面,那么您将错过该环境自动执行常见任务或充分利用各种工具的某些功能的能力。此外,您不能组合工具来创建自定义宏工具。gui的优点是所见即所得(whatyouseeiswhatyouget)。缺点是所见即所得(whatyouseeisallyouget)。作为一个务实的程序员,您总是希望执行特殊操作(GUI可能不支持的操作)。当您想快速组合几个命令来完成查询或其他一些任务时,cli更适合。例如:查看上周有哪些js文件没有被更改:#cli:find.-name'*.js'-mtime+7-print#gui:1.点击进入“FindFiles”,点击在“文件名”字段中,键入“*.js”并选择“修改日期”选项卡;2.然后选择“之间”。单击“开始日期”并输入项目开始的日期。3.点击“结束日期”,输入一周前的日期(确保手头有日历),然后点击“开始搜索”;如何开发cli工具?基本上,任何成熟的语言都可以用来开发cli工具。作为前端新手,JavaScript比较方便,所以我们选择node作为开发语言。创建一个项目#1。创建目录:mkdirkid-cli&&cdkid-cli#2。因为我们最终会将cli发布到npm,所以需要初始化一个包:npminit#3。创建一个index.js文件touchindex.js#4.打开编辑器(vscode)代码。安装code命令,运行VScode打开命令面板(??P),然后输入shell命令找到:Install'code'commandinPATH。打开index.js文件,添加一段测试代码:#!/usr/bin/envnodeconsole.log('helloworld!')要在终端运行node程序,需要先输入node命令。比如nodeindex.js可以正确输出helloworld!,代码最上面的#!/usr/bin/env节点告诉终端这个文件应该使用node来执行。创建命令一般cli都有一个特定的命令,比如git,刚才用到的代码等,我们还需要设置一个命令,我们就叫kid吧!如何让终端识别这个命令?很简单,打开package.json文件,添加一个字段bin,声明一个命令关键字和对应的执行文件:#package.json……"bin":{"kid":"index.js"},...如果要声明多个命令,只需修改该字段即可。那我们测试一下,在终端输入kid,会提示:zsh:commandnotfound:whyiskidlikethis?回想一下,通常我们在使用cli工具的时候,都是需要先安装的,比如vue-cli,在使用之前需要全局安装:npmivue-cli-g而我们的kid-cli还没有在npm上发布,的当然不是已经安装了,所以终端还不能识别这个命令。通常我们想在本地测试一个npm包。我们可以使用命令:npmlink在本地安装包。让我们执行:npmlink然后执行kid命令来查看helloworld!的正确输出。至此,一个简单的命令行工具就完成了,不过这个工具没什么用,别着急,我们来一点一点的增强它的功能。查看版本信息,首先是查看cli的版本信息。希望通过以下命令查看版本信息:kid-v这里有两个问题。如何获取-v参数?如何获取版本信息?在node程序中,命令的参数可以通过process.argv获取,返回为数组,修改index.js,输出这个数组:console.log(process.argv)然后输入任意命令,如:kid-v-h-lalalacontrol本站会输出['/Users/shaolong/.nvm/versions/node/v8.9.0/bin/node','/Users/shaolong/.nvm/versions/node/v8.9.0/bin/kid','-v','-h','-lalala']这个数组的第三个参数就是我们要的-v。第二个问题,版本信息一般放在package.json文件的version字段中,require进去即可。修改后的index.js代码如下:#!/usr/bin/envnodeconstpkg=require('./package.json')constcommand=process.argv[2]switch(command){case'-v':console.log(pkg.version)breakdefault:break}然后我们执行kid-v输出版本号。初始化一个项目接下来我们来实现一个最常用的功能,使用cli来初始化一个项目。整个过程大致是这样的:cd到你要新建项目的目录;执行kidinit命令,根据提示输入项目名称;cli通过git拉取模板项目代码,复制到项目名所在目录;为了实现这个过程,我们需要解决以下问题:执行复杂的命令在上面的例子中,我们通过process.argv获取命令的参数,但是当一个命令有多个参数,或者需要用户输入项目名称(我们称之为“问答”)命令,一个简单的switchcase被拉长了。这里我们引用一个专门处理命令行交互的包:commander。npmicommander--savethentransformindex.js#!/usr/bin/envnodeconstprogram=require('commander')program.version(require('./package.json').version)program.parse(process.argv)运行kid-h会输出Usage:kid[options][command]Options:-V,--versionoutputtheversionnumber-h,--helpoutputusageinformationcommander已经为我们创建了帮助信息,还有两个参数-V和-h,在上面的代码程序中.version是返回版本号,和前面的功能一致。program.parse是将命令参数传入commander管道,一般在***上执行。添加Q&A操作接下来,我们添加kidinit的Q&A操作。这里需要引入一个新的包:inquirer。该包可以通过简单的配置使cli支持问答交互。npmiinquirer--saveindex.js:#!/usr/bin/envnodeconstprogram=require('commander')varinquirer=require('inquirer')constinitAction=()=>{inquirer.prompt([{type:'input',message:'请输入项目名称:',name:'name'}]).then(answers=>{console.log('项目名称:',answers.name)console.log('正在复制项目,请稍候等')})}program.version(require('./package.json').version)program.command('init').description('Createproject').action(initAction)program.parse(process.argv)program.command可以定义一个命令,description添加一个描述,显示在--help中,action指定一个回调函数来执行命令。Inquirer.prompt可以接收一组问答对象。type字段表示问题和答案的类型,name指定答案的key。您可以通过答案中的名称获取用户的输入。有许多类型的问题和答案。这里我们使用input来允许用户输入项目名称。运行kidinit,然后你会被提示输入一个项目名,这个名字会被打印出来。运行shell脚本熟悉git和linux的同学可以用几个词来初始化一个项目:gitclonexxxxx。你只需要安装shelljs包就可以轻松搞定。npmishelljs--save假设我们要克隆github上vue-admin-template项目的代码,自动安装依赖,修改index.js,在initAction函数中加入执行shell脚本的逻辑:#!/usr/bin/envnodeconstprogram=require('commander')constinquirer=require('inquirer')constshell=require('shelljs')constinitAction=()=>{inquirer.prompt([{type:'input',message:'请输入项目名称:',name:'name'}]).then(answers=>{console.log('项目名称:',answers.name)console.log('正在复制项目,请稍候')constremote='https://github.com/PanJiaChen/vue-admin-template.git'constcurName='vue-admin-template'consttarName=answers.nameshell.exec(`gitclone${remote}--depth=1mv${curName}${tarName}rm-rf./${tarName}/.gitcd${tarName}npmi`,(error,stdout,stderr)=>{if(error){console.error(`execerror:${error}`)return}console.log(`${stdout}`)console.log(`${stderr}`)});})}program.version(require('./package.json').version)program.command('init').description('Createproject').action(initAction)program.parse(process.argv)shell.exec可以帮我们执行一个脚本,脚本执行的结果可以在回调函数中输出。测试我们的初始化函数:cd..kidinit#输入一个项目名可以看到cli已经自动从github上拉取了vue-admin-template的代码,放到了指定目录下,并自动帮我们安装了依赖。结语***别忘了把你的cli工具发布到npm,供更多同学使用。npmpublish怎么样?是不是觉得看似神秘的命令行开发其实没什么技术含量?上面的列表只是cli开发的冰山一角。要开发强大的cli工具,除了熟悉node和常用工具包外,更重要的是了解linux的常用命令和文件系统。希望所有的同学都能受到启发,开发自己的cli工具。安利时间前端的技术点很多,其中有很多抽象晦涩的知识点,无法用文字直观的表达出来,所以很多开发者对这些知识点的理解是真假。如果我们通过图片来展示,就会很容易理解。因此,Diagram项目希望开发者可以通过这种方式了解前端技术领域的知识点。