当前位置: 首页 > 后端技术 > Node.js

实现一个web代码模板快速生成CLI工具

时间:2023-04-03 15:46:51 Node.js

前言上一篇我们实现了一个通用的web工程脚手架工具,目的是快速搭建项目。在实际开发中,尤其是后台管理系统,类似的代码实现还有很多。于是乎,我们可以继续实现一个快速生成网页代码模板的工具,告别复制/粘贴。基本流程的基本思路其实很简单,就是通过命令调用定义好的模板,然后生成代码文件:项目结构xman-tcli├─bin│└─xmant.js├─command│├─createFile.js│└─createManyFiles.js├─配置│└─fileList.js├─模板│├─index.js│├─js││├─reactClassJSX.js││└─reactFuncJSX.js│└─ts│├─reactClassTSX.js│├─reactFuncTS.js│└─reactFuncTSX.js├─utils│└─index.js├─.gitignore├─LICENSE├─package.json└─README.md实现了许多有用的功能dependencies在上一篇文章中有提到,所以本文不再过多介绍。初始化项目可以使用npminit创建,也可以根据下面列出的package.json进行修改。{"name":"xman-tcli","version":"1.0.0","description":"web-cli工具,可以快速创建模板","bin":{"xmant":"bin/xmant.js"},"scripts":{"test":"echo\"Error:notestspecified\"&&exit1"},"repository":{"type":"git","url":"https://github.com/XmanLin/xman-tcli.git"},"keywords":["cli"],"author":"xmanlin","license":"MIT","dependencies":{"chalk":"^4.1.2","clui":"^0.3.6","commander":"^8.2.0","figlet":"^1.5.2","handlebars":"^4.7.7","inquirer":"^8.1.5","update-notifier":"^5.1.0"}}writebin/xman.js#!/usr/bin/envnodeconst{program}=require('指挥官');程序.version(要求('../package').version,'-v,--version');程序.parse(process.argv);//这里是必须的if(!program.args.length){program.help();}在当前xmant-cli目录下,执行npmlink后,可以在本地调试脚手架工具。然后在当前目录下执行:xmant-v,说明项目初步构建成功。通过命令快速创建单个代码模板编写模板可根据实际项目提取代码模板。这里有几个简单的模板作为例子。templates/js/reactClassJSX.jsreturn`import*asReactfrom'react';exportclass${className}extendsReact.Component{constructor(props){super(props);}this.state={}}componentDidMount(){}render(){return(

)}}`}templates/js/reactFuncJSX.jsmodule.exports=function(funcName){return`importReact,{useEffect,useState}from'react';const${funcName}=(props)=>{return(
)}exportdefault${funcName};`}templates/ts/reactClassTSX.jsmodule.exports=function(className){return`import*asReactfrom'react';interfaceProps{}interfaceState{}exportclass${className}extendsReact.Component{构造函数(道具:道具){超级(道具);this.state={}}componentDidMount(){}render(){返回(
)}}`}templates/ts/reactFuncTS.jsmodule.exports=function(funcName){return`exportconst${funcName}=()=>{}`}templates/ts/reactFuncTSX.jsmodule.exports=function(funcName){return`importReact,{useEffect,useState}from'react';const${funcName}=(props:any)=>{useEffect(()=>{},[])return(
)}exportdefault${funcName};`}模板定义好后,可以通过index.js统一导出templates/index.jsconstreactClassJSX=require('./js/reactClassJSX');constreactFuncJSX=require('./js/reactFuncJSX');constreactClassTSX=require('./ts/reactClassTSX');constreactFuncTSX=require('./ts/reactFuncTSX');constreactFuncTS=require('./ts/reactFuncTS');//命名约定:名称以“-”连接,前面是模板名,后面是创建文件的后缀模块。exports=[{name:'reactClass-jsx',src:reactClassJSX},{name:'reactFunc-jsx',src:reactFuncJSX},{name:'reactClass-tsx',src:reactClassTSX},{name:'reactFunc-tsx',src:reactFuncTSX},{name:'reactFunc-ts',src:reactFuncTS}]这里的“命名规范”是为了后面创建文件时获取对应的后缀。创建实用函数utils/index.js:module.exports={getFileSuffix:(name)=>{if(typeofname==='string'){returnname.split('-')[1]}}}write创建文件逻辑就绪,接下来是文件创建逻辑command/createFile.js://创建单个文件consttemplates=require('../templates/index');constchalk=require('粉笔');constinquirer=require('inquirer');constfs=require("fs");constutils=require('../utils/index');module.exports=()=>{inquirer.prompt([{name:'templateName',type:'list',message:'请选择你要生成的代码模板:',choices:templates},{name:'filename',type:'input',message:'请输入代码文件中的类名或方法名:',validate:function(value){if(value.length){returntrue;}else{return'Please在代码文件中输入类名或方法名';}},}]).then(answers=>{consttemplateName=answers.templateName;constfilename=answers.filename;templates.forEach((item)=>{if(item.name===templateName){constsuffix=utils.getFileSuffix(item.name)constfile=`./index.${suffix}`//检查是否有是当前文件夹中的同名文件fs.access(file,function(err){if(!err){console.log('创建失败:',chalk.yellow('文件已经存在'))}else{fs.writeFile(file,item.src(filename),function(err){if(err){console.log('创建失败:',chalk.red(err))}else{console.log(chalk.green(`创建文件成功!${file}`));}})}})}})})}这里注意:如果在创建文件前没有检查当前文件如果有文件夹下有同名文件,覆盖原同名文件写命令就是写bin/xman.js的最后一个命令:#!/usr/bin/envnodeconst{program}=require('commander');...program.command('create').description("Create一个文件").alias('c').action(()=>{require('../command/createFile')()});...debug在当前项目文件夹下执行npmlink--force,然后找一个文件执行xmantc:打开我们新建的文件可以看到:也可以选择其他模板创建试试。通过命令快速批量创建代码模板如果我们想一次性创建大量的代码模板怎么办?当然是通过命令批量创建文件。这里的思路:通过读取配置文件,然后批量创建。编写配置文件//说明://folder:文件夹名,可以嵌套,以“/”分隔//fileName:文件名//funcName:类名或函数名//template:使用的文件模板模块。exports=[{folder:'./home',fileName:'index',funcName:'Home',template:'reactFunc-tsx'},{folder:'./home/compnent',fileName:'index',funcName:'Compnent',template:'reactFunc-tsx'},{folder:'./home/service',fileName:'index',funcName:'service',template:'reactFunc-ts'},{文件夹:'./news',fileName:'index',funcName:'News',template:'reactFunc-tsx'},{folder:'./news/service',fileName:'index',funcName:'service',template:'reactFunc-ts'}]这里使用的文件模板就是我们之前写的模板。编写批量创建文件逻辑根据配置文件批量创建文件夹和文件command/createManyFiles.js://批量创建文件constchalk=require('chalk');constinquirer=require('inquirer');constfs=require('fs');constpath=require('path');constutils=require('../utils/index');constfileList=require('../config/fileList');consttemplates=require('../templates/index');constclui=require('clui');constSpinner=clui.Spinner;conststatus=newSpinner('Creating...');//递归创建目录同步方法functionmkdirsSync(dirname){if(fs.existsSync(dirname)){returntrue;}else{if(mkdirsSync(path.dirname(dirname))){fs.mkdirSync(dirname);console.log(chalk.green(`创建目录成功-${dirname}`));}}}module.exports=()=>{inquirer.prompt([{name:'choices',type:'list',message:'请确认配置好的模板批量生成列表',choices:['yes','不']}]).then(answers=>{constchoices=answers.choicesif(choices==='yes'){//批量创建目录fileList.forEach(item=>{if(item.folder){mkdirsSync(`${item.folder}`)}})//批量创建文件文件列表。forEach(item=>{templates.forEach(tpl=>{if(item.template===tpl.name){constsuffix=utils.getFileSuffix(item.template)constfileName=`${item.fileName}.${suffix}`fs.writeFile(`${item.folder}/${fileName}`,tpl.src(item.funcName),function(err){if(err){console.log('创建失败:',chalk.red(err))}else{console.log(chalk.green(`文件创建成功!${fileName}`));}})}})})}})}写命令最后写bin/xman.js:#!/usr/bin/envnodeconst{program}=require('commander');...program.command('create-many').description("创建多个文件夹和文件").alias('cm').action(()=>{require('../command/createManyFiles')()});...debug在当前项目文件夹下执行npmlink--force,然后找一个文件执行xmantcm:看看我们批量创建的文件和文件夹:总结一下,快速创建代码模板的方法有很多,包括VSCode插件,CLI工具,以及制作lowcode/nocode平台的方法等。本文这种方法的优点是足够灵活,我们可以根据具体的需求进行灵活的修改,使其更加适用。