资讯专栏INFORMATION COLUMN

如何搭建CLI脚手架

社区管理员 / 767人阅读

一、CLI有啥用,认识CLI

前端开发过程中常见的CLI有:

  • create-react-app

  • vue-cli

  • webpack-cli

  • prettier-cli

基本复杂一点的工具都在集成CLI,为啥都要搞成CLI呢?

因为CLI可以提供更强大的功能:

  • 通过命令搭配实现不同的功能

  • 管理项目模版

  • 启动本地服务

  • 生成模版文件

  • 对代码进行格式化

二、搭建一个最简单的CLI

我们先搭建一个最简单的CLI来体验下,然后逐步实现复杂点的功能。

1、新建项目

首先新建项目作为CLI源代码地址

mkdir cli-demo cd cli-demo npm init 复制代码

2、安装依赖

yargs文档配置:该插件将用户通过终端输入的参数解析成对象,可以配置各种参数。

yarn add yargs 复制代码

命令使用语法:

.command(cmd, desc, [builder], [handler]) 复制代码

3、CLI命令配置

下面的配置说明:

  • 配置命令get

  • 声明信息make a get HTTP request

  • 并配置了参数url信息

  • 最后callback函数获取用户执行的参数

具体使用:编辑index.js,第一行一定要加注释,表明运行在node环境下

#!/usr/bin/env node const yargs = require('yargs/yargs') const { hideBin } = require('yargs/helpers') yargs(hideBin(process.argv))   .command(     'get',     'make a get HTTP request',     function (yargs) {       return yargs.options({         url: {             alias: 'u',             describe: 'the URL to make an HTTP request to'         }       })     },     function (argv) {       console.log("callback", argv.url)     }   )   .help()   .argv 复制代码

执行命令,可以获取输入的参数

image.png

这里get就是定义的指令,url是指令下的key值,用--url输入,alias就是别名,用-u表示,后面跟要输入的参数。

3、npm发布

接着我们发布下npm,然后一个CLI就完成了。

登陆npm仓库,没有的话去注册一个,地址

npm login 复制代码

选择一个中意的cli名字,查一下是否存在,这里我们起个名字cli-demo3

image.png

执行npm version patch && npm publish --registry=https://registry.npmjs.org,不出意外的话,就发布成功了。

image.png

4、下载使用

然后我们本地使用下,首先下载到本地,全局下载npm install -g cli-demo3

image.png

cli-demo3是我们前期测试使用写的CLI,后面继续使用我正常部署的CLI:u-amin-cli,原理是一样的

三、终端交互优化

1、log-symbols:输出结果用图标标识

# 这里使用4版本,升级到5版本不再支持require方式导入 yarn add log-symbols@4.1.0 复制代码

使用方法

image.png

使用效果

image.png

2、chalk:打印出各种颜色的文案提示,功能强大,几乎支持所有的颜色

# 这里使用4版本,升级到5版本不再支持require方式导入 yarn add chalk@4.1.2 复制代码

1、支持传入string,array和模版字符串

使用方法

console.log(chalk.blue("this is blue")) console.log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz')); console.log(` CPU: ${chalk.red('90%')} RAM: ${chalk.green('40%')} DISK: ${chalk.yellow('70%')} `); 复制代码

使用效果

image.png

2、支持修改背景色、各种颜色格式、指定不同文本的颜色

使用方法

console.log(chalk.blue.bgRed.bold('Hello world!')); console.log(chalk.red('Hello',  chalk.underline.yellowBright('world') + '!')); console.log(chalk.hex('#DEADED').underline('Hello, world!')) console.log(chalk.rgb(15, 100, 204).inverse('Hello!')) 复制代码

使用效果

image.png

3、支持自行封装一些颜色

使用方法

const error = chalk.bold.red; const warning = chalk.hex('#FFA500'); // Orange color console.log(error('Error!')); console.log(warning('Warning!')); 复制代码

使用效果

image.png

3、ora:增加loading效果

# 这里使用5版本,升级到6版本不再支持require方式导入 yarn add ora@5.4.1 复制代码

使用方法

const ora = require('ora');   const spinner = ora('Loading unicorns').start();   setTimeout(() => {     spinner.color = 'yellow';     spinner.text = 'Loading rainbows'; }, 1000); 复制代码

使用效果

image.png

4、inquirer:在终端选择命令

使用方法

var inquirer = require('inquirer'); inquirer   .prompt([     {       name: "templateType",       type: "list",       default: "vue",       choices: [         {           name: "React",           value: "react",         },       ],       message: "Select the template type.",     }   ])   .then((answers) => {     // Use user feedback for... whatever!!   })   .catch((error) => {     if (error.isTtyError) {       // Prompt couldn't be rendered in the current environment     } else {       // Something else went wrong     } }); 复制代码

使用效果

image.png

这样就可以给客户提示选择来处理逻辑。

5、download-git-repo:download Git仓库

使用方法

const download = require("download-git-repo"); download('direct:https://gitlab.com/flippidippi/download-git-repo-fixture.git#my-branch', 'test/tmp', { clone: true }, function (err) {   console.log(err ? 'Error' : 'Success') }) 复制代码

还有很多类似的插件,来丰富cli的功能,根据需要添加即可

  • open 打开浏览器

  • yargs/commander 执行cli命令

  • get-port 获取当前端口号

四、CLI优化

1、提取命令行配置到一个文件中

启动文件index.js

const yargs = require('yargs/yargs') const { hideBin } = require('yargs/helpers') const config = require('./config') const yargsCommand = yargs(hideBin(process.argv)) config.forEach(commandConfig => {   const { command, descriptions, options, callback } = commandConfig   yargsCommand.command(     command,     descriptions,     yargs => yargs.options(options),     (argv, ...rest) => {       callback(argv, ...rest);     }   ) })    yargsCommand.help().argv 复制代码

指令文件config.js

const commandOptions = [   {     command: "create",     descriptions: "拉取一个项目模版",     options: {       name: {         alias: "n",         type: "string",         require: true,         describe: "项目名称",       },     },     callback: async (argv) => {       create({name: argv.name})     } }] 复制代码

提取配置,就很清晰了

2、配置ESLint和Prettier,之前专门写了自动化检查代码的文章。

前端工程化:Prettier+ESLint+lint-staged+commitlint+Hooks+CI 自动化配置处理

3、提取脚本生成使用文档

上一步我们对配置进行了提取,接着根据配置生成使用文档,如下

image.png

使用方法

yarn add json2md@1.12.0 -D 复制代码

const json2md = require("json2md") // 按json2md需要的数据格式组合 const data = json2md([     { h1: "JSON To Markdown" }   , { blockquote: "A JSON to Markdown converter." } ])) // 写入Readme.md文档 fs.writeFile(path.join(__dirname, "../Readme.md"), json2md(data), (err) => {   if (err) throw err;   console.log("update docs success"); }); 复制代码

五、CLI管理模版项目

1、配置下载命令

{     command: "create",     descriptions: "拉取一个项目模版",     options: {       name: {         alias: "n",         type: "string",         require: true,         describe: "项目名称",       },     },     callback: async (argv) => {       create({name: argv.name})     } } 复制代码

2、准备模版文件列表

const map = {    vue: "https://github.com/luchx/ECHI_VUE_CLI3.0.git",    react: "git@github.com:richLpf/antd-template-demo.git#main" } 复制代码

3、下载逻辑

1、inquirer提示用户选择对应的模版,具体可以看前面用法

2、通过download下载模版文件

module.exports = function downloadFromRemote(url, name) {   return new Promise((resolve, reject) => {     download(`direct:${url}`, name, { clone: true }, function (err) {       if (err) {         reject(err);         return;       }       resolve();     });   }); }; 复制代码

3、通过ora在下载过程中展示loading

image.png

这是主要的下载逻辑,关于日志,我们可以更好的展示,也可以配置更复杂的命令:替换下载的项目名称,删除.git目录,修改package.json配置

六、通过CLI启动API模拟接口服务

前端在开发的过程中,总会遇到后端接口无法按时提供的情况,这种情况下有很多解决方案,常见的通过客户端生成模拟api,在项目中引入Mock。

这里我们通过CLI来实现一个更加简单好用的模拟方案

1、方案原理

通过CLI启动一个或多个服务器,通过Express做路由转发本地的JSON文件

2、命令配置

首先我们配置mock命令,设定参数typeportcreate分别代表API类型、启动Http服务器端口号,默认9000,create是否自动生成接口数据JSON文件。

{     command: "mock",     descriptions: "启动一个本地服务,模拟返回接口数据",     options: {       type: {         alias: "t",         type: "string",         default: "action",         describe: "选择API类型",         choices: ['action', 'restful']       },       port: {         alias: "P",         type: "number",         default: 9000,         describe: "选择启动的端口号",       },       create: {         alias: "c",         type: "boolean",         default: false,         describe: "如果mock目录不存在是否自动创建,默认不自动创建"       },     },     callback: async (argv) => {       mock({         ...argv       })     } 复制代码

3、Http服务处理

1、启动express服务器,配置参数解析和跨域设置,并获取mock数据的目录,启动Http服务器

const app = express() app.use(bodyParser.json({limit: '50mb'})) app.use(express.urlencoded({ extended: true })); app.all('*', (req, res, next) => {     res.header('Access-Control-Allow-Origin', '*'); //访问控制允许来源:所有     res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept'); //访问控制允许报头 X-Requested-With: xhr请求     res.header('Access-Control-Allow-Metheds', 'PUT, POST, GET, DELETE, OPTIONS'); //访问控制允许方法     res.header('X-Powered-By', 'nodejs'); //自定义头信息,表示服务端用nodejs     res.header('Content-Type', 'application/json;charset=utf-8');     next(); }); const filePath = path.join(process.cwd(), `./mock/`) app.listen(port, () => console.log(`Mock api listening on port ${port}!`)); 复制代码

2、如果是Action类型的API

比如请求url为:

http://localhost:9000/acl 复制代码

请求体为:

{     Action: "GetUsers" } 复制代码

此时在CLI执行的目录,新建mock/acl/GetUsers.json

GetUsers.json内容为返回的json数据

{     "RetCode": 0,     "Message": "this is error",     "Data": [] } 复制代码

然后通过fs模块读取json文件的数据,直接返回模拟的数据,因为是实时读取的,所以更新json数据不需要重启服务。主要逻辑如下

app.post('*', async(req, res) => {     const key = req.params[0].substring(1)     const { Action } = req.body     const file = `${filePath}${key}/${Action}.json`;     fs.readFile(file, 'utf-8', function(err, data) {         if (err) {             res.send(NotFoundResponse);         } else {             res.send(data);         }     }) }) 复制代码

3、如果是Restful类型的API

比如请求url为:

http://localhost:9000/acl/users 复制代码

post请求体为:

{     limit: 10 } 复制代码

此时在CLI执行的目录,新建mock/acl/users/post.json

post.json内容为返回的json数据

{     "RetCode": 0,     "Message": "get users",     "Data": [] } 复制代码

如果是get请求,只需要添加get.json就可以了。

然后同样通过fs读取对应的json数据

app.all("*", async(req, res) => {     const key = req.params[0]     const method = req.method     const file =`${filePath}${key}/${method}.json`     console.log("file", file)     fs.readFile(file, 'utf-8', function(err, data) {         if (err) {             res.send(NotFoundResponse);         } else {             res.send(data);         }     }) }) 复制代码

这样就完成了CLI启动一个模拟的http服务,用起来很方便,并且可以支持直接在项目中使用。

具体可以试试看u-admin-cli

对于大部分mock来说,复杂的配置是不需要的,这里仅仅是用了固定的json数据,我觉得就够用了,当然还可以自行处理数据,引入Mock规则,自行定义生成数据类型等

以上就是搭建一个CLI的过程,我们从最简单的开始构建了一个基础CLI,在这个基础上进行了交互优化,然后实际开发了CLI的两个功能:

  • 1、通过CLI管理部门内的模版项目

  • 2、通过CLI启动Http服务器,模拟接口生成

项目代码:github.com/richLpf/u-a…

CLI地址:www.npmjs.com/package/u-a…

码字不易,欢迎点赞????,有问题请留言。


作者:前端中后台
链接:https://juejin.cn/post/7090001607596703758
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/127965.html

相关文章

  • 从零开始搭建自己的前端手架(一)

    摘要:以下阅读将花费分钟前言日常开发中,我们都只专注在业务上的开发,拿起一套开箱即用的模板项目就直接开搞了,不知道大家有没有思考过,平时我们使用的脚手架里面到底做了什么,并且如果是自己来搭一套脚手架,应该怎么去搭呢在本博客中,将记录作者搭建脚手架 (以下阅读将花费10分钟) 前言 日常开发中,我们都只专注在业务上的开发,拿起一套开箱即用的模板项目就直接开搞了,不知道大家有没有思考过,平时我们...

    gxyz 评论0 收藏0
  • 为什么我不推荐你使用vue-cli创建手架

    摘要:后来经过排查你会发现是由于目前还没有版本。可以使用该方式解决。这就是我为什么不推荐你使用创建脚手架的原因此文的受众是想要进阶中级的初级前端人员。 最近在知乎看到一个问题,原问题如下: 很奇怪,为什么现在能找到自己手动创建vue脚手架的文章非常少,而且大家似乎对webpack4的热情并不高,对于想基于vue2.0+webpack4搭建一个脚手架的我来说资料真是少得可怜。难道现在一般的做...

    trigkit4 评论0 收藏0
  • 【骨架屏】【vue】如何在webpack+vue+vue-cli搭建多模块/单模块多路由骨架屏

    摘要:如何在下搭建多模块单模块多路由骨架屏前言骨架屏的用户感知比更好,此前看过很多专栏以及文章,此次实践中还是遇到需要学习的部分。包括因为可能信息面不全,对插件源码进行了详细解读,希望对于将要在项目中搭建骨架屏的小伙伴们有所帮助。 如何在webpack+vue+vue-cli下搭建多模块/单模块多路由骨架屏 前言 骨架屏的用户感知比loading更好,此前看过很多专栏以及文章,此次实践中还是...

    huhud 评论0 收藏0
  • 【骨架屏】【vue】如何在webpack+vue+vue-cli搭建多模块/单模块多路由骨架屏

    摘要:如何在下搭建多模块单模块多路由骨架屏前言骨架屏的用户感知比更好,此前看过很多专栏以及文章,此次实践中还是遇到需要学习的部分。包括因为可能信息面不全,对插件源码进行了详细解读,希望对于将要在项目中搭建骨架屏的小伙伴们有所帮助。 如何在webpack+vue+vue-cli下搭建多模块/单模块多路由骨架屏 前言 骨架屏的用户感知比loading更好,此前看过很多专栏以及文章,此次实践中还是...

    MkkHou 评论0 收藏0
  • vue.js使用vue-cli搭建一个SPA项目

    摘要:之所以写这篇如何运用脚手架自动化构建出一个项目的大架构,主要是面向想入门的小伙伴。之前,我第一次接触,一直摸不着头脑,想在网上搜个接地气的教程都找不到。 WHY 之所以写这篇如何运用脚手架自动化构建出一个项目的大架构,主要是面向想入门vue的小伙伴。之前,我第一次接触vue,一直摸不着头脑,想在网上搜个接地气的教程都找不到。SO,我以如何搭建结构为开始,向想入门vue的童鞋们把我仅有的...

    CrazyCodes 评论0 收藏0

发表评论

0条评论

社区管理员

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<