10分钟,打造一个专属于你的cli

7,477 阅读8分钟

这是我参与2022首次更文挑战的第 1 天,活动详情查看:2022首次更文挑战

大家好!我是小杜杜,是一名摸鱼前端工程师,今天聊一聊前端工程化,并讲解下如何花十分钟打造一个专属于自己的cli,希望大家可以多多讨论留言,一起来探讨下前端工程化,有什么高大上的方法留言指出~

前言

作为一个开发人员,相比大家都知道 npm 这个命令,npm是什么呢?简单的说npmnode.js一个包的管理工具。

其实我在很久之前就看到一个比较酷炫的展示,就是Taro

image.png

当然这里介绍的并不是taro,而是说 taro 已经成为了一个 Taro“代言人”,简单说 就像诗歌,看到将进酒就是李白,登高就是杜甫一样,所以接下来就讲解如何创建一个专属于我们的命令,让他成为自己的代言人😎

5分钟创建一个属于自己的命令

创建一个npm账号并登录

首先我们需要在 npm 官网上注册一个属于自己的账号,然后在命令行中进行登录

 npm login
 npm notice Log in on https://registry.npmjs.org/
 
 Username: ...
 PassWord: ...
 Email: ...

这里我们要注意尤其注意两点:

  • 地址必须为 registry.npmjs.org/ ,不能是http的
  • node 的版本为 7.0.0以上版本,原因是现在node不支持TLS 1.2以下的

初始化一个项目

这是我们需要创建一个包,比如说 domesy-cli,先要在npm 官网上搜索一下,查看这个包是否注册过,如果没有,那么恭喜你,可以使用此包名

image.png

接下来创建一个 domesy-cli 的文件夹,并在此项目执行 npm init,这时会创建一个为package.json的文件夹,然后我们需要使用bin

{
  "name": "domesy-cli",
  "version": "0.0.1",
  "description": "domesy命令",
  "main": "index.js",
  "bin": {
    "domesy": "bin/domesy.js"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "domesy",
  "license": "ISC"
}

domesy 就是属于我的代名词, 而bin/domesy.js代表这文件目录

发布

然后我们执行 npm publish 即可

这时我们在 npm 官网 上看看

image.png

注:

  • 如果想要再次更新,我们需要 改变 package.json 中的 version 才能使用 npm publish
  • 如果你想删除的话,使用命令 npm unpublish -f 包名 即可

使用

当我们发布成功后,就要使用刚才的命令,我们使用 npm install -g domesy-cli 下载到本地,而在bin中的命令 domesy 也可使用了

注意:目前可以使用domesy命令,但还没有写具体操作,所以没有任何效果,接下来讲讲一些基本操作

打造一个专属的cli

通过上面的4步,我们已经如愿的创造出属于自己的代名词 domesy,接下来我们直接讲讲如何打造一个专属的cli。

我先做一个我完成后的cli是个什么样子吧,这样更方便讲解(● ̄(エ) ̄●)

image.png

简单分析下实现的功能:

  • 第一个和第二个是下载我的两个项目,一个是PC端,另一个是移动端,如果大家感兴趣可以用cli下载看看哦(另外可以看看,文章最后的文档,讲了下如何配置属于自己的项目,多多支持下😎)
  • 第三个和第四个主要是安装依赖运行程序的操作,可能有点鸡肋,勿喷哦~
  • 第五个就是查看当前包的版本号
  • 第六个纯粹是退出,方便用户直接退出,是不是很贴心😁

安装依赖

我在掘金发的第一篇文章中:打造开箱即用的 react 移动端框架 讲解了一个小玩意

image.png

在打包的时候打个大大的 'DOMESY!' 当做自己的”标识“,题外话了,直接介绍需要安装的插件吧~

  • clear: 清屏
  • chalk: 装饰作用,使之终端上的输出加上颜色
  • figlet: 作用是将字母转化为图片,使之更加醒目
  • git-pull-or-clone:将代码下载
  • inquirer: 在命令行中打出交互式的命令

主要就这5个插件了。

画个大大的标识 DOMESY!

当我们想画个大大的标识的时候,就需要使用 chalkfiglet 这两个插件,话不多说直接上代码:

 // lib/api.js
 const chalk = require("chalk");
 
 module.exports.log = (msg, color='green', ...arg) => console.log(chalk[color](msg, arg));
 
 // bin/domesy.js
 const figlet = promisify(require("figlet"));
 const clear = require("clear");
 
 clear(); //在执行的时候清空下控制台会更好哦~

 log(
  figlet.textSync("DOMESY !", {
    horizontalLayout: "Isometric1",
    verticalLayout: "default",
    width: 80,
    whitespaceBreak: true,
  }), 'blue'
 )

下载项目

在下载项目需要的流程

  • 首先要指定一个文件夹,来下载项目,所以这里需要使用 inquirer来做个简单的交互,告诉用户我要下载什么
  • 其次要通过 git-pull-or-clone 来处理要下载的地址(由于git老那啥,所以我把项目同步到了gitee)
  • 然后我们打印下,告知用户正在下载即可
module.exports = async () => {
  console.log("path", resolve("."));
  // 项⽬名称
  const name = await inquirer.prompt([{
    type: 'input',
    message: '设置文件名😎😎😎',
    name: 'name',
    default: "react-mobile" // 默认值
  }])
  const repo = 'https://gitee.com/domesy/react-mobile.git'
  const desc = resolve(`./${name.name}`);
  console.log("desc", desc);
  const process = ora(` 🚗🚗🚗下载中.....${repo}`);
  process.start();
  try {
    await download(repo, desc);
    process.succeed();
    log(` 🚗🚗🚗下载完成`);
  } catch (e) {
    console.log(e);
    process.fail();
  }
};

达到这样的效果

image.png

安装依赖

当我们下载完成后,肯定先要安装依赖,所以我们需要使用 child_process这个模块,并将其封装,这样的目的是:可以不用进入文件,直接操作

 // 封装 spawn lib/api.js
 module.exports.spawn = async (...args) => {
  const { spawn } = require('child_process');
  return new Promise(resolve => {
    const proc = spawn(...args)
    proc.stdout.pipe(process.stdout)
    proc.stderr.pipe(process.stderr)
    proc.on('close', () => {
      resolve()
    })
  })
 }

我们只需要进入这个文件夹,然后执行 yarn install即可

   log('🚴🏻🚴🏻🚴🏻安装依赖中,请稍等....')
   await spawn("yarn", ['install'], { cwd: `${name.name}/`})
   log('🚴🏻🚴🏻🚴🏻安装完成')

同时我们可以使用 fs.existsSync这个命令,检查下node_module是否安装,从而是自己的cli更加完美一点

这时我们来看看 安装依赖这个功能:

image.png

做了这三个小功能,但要注意下自定义文件夹,我希望你直接将项目拖到控制台这,然后执行,但拖过的文件会有空格,导致无法安装,所以这里需要借助下 trim() 取除下空格

启动项目

启动项目的方式与安装依赖的方式一样,只是命令不同,执行:await spawn("yarn", ['run', 'start'], { cwd: desc})即可

然后我们可以利用这些,对自己的cli完善就行了(● ̄(エ) ̄●)

讨论

在这里,已经完成了cli的基本操作,可能这时有人会说前端就是花里胡哨,感觉这些基本没什么用,其实不然,我在文章的一开头说过一个词:前端工程化

这个词,说实话说近不近说远不远,其实在大多数公司中,要的只是将项目做出来,并不会管你,甚至不管代码规范,只要将需要的产品做出来即可,这都是题外话,就不胡扯了😄

想问问大家是如何处理公共组件的,当不同的项目使用公共组件是如何处理的?

一开始,我是直接将组件手动复制到另一个项目中,这种方式也是最为简单的,也是最low的,在大型开发中,多人协作中明显不适用。

后面接触到 git submodule这个命令,通过它我们也可以进行公共组件的配置

但我觉得 git submodule始终太麻烦了,于是问了下大佬们如何处理的,他们使用的方法就像下载包一样,直接通过 npm 来下载,(只是换成了内网),这种方式确实感觉蛮高大上的,也确实比较方便,所以变有了这篇文章,以此来总结下,O(∩_∩)O哈哈~

如果我是前端的leader,一定会使用这种方式对项目进行管理,这样简直爽翻天😎😎😎

大家有什么更好的方式,欢迎在下方评论区讨论~

扩展

在上述的讲解中,我只是讲了最为基本的,其实cli真正的功能不止于此,用过 umi 的小伙伴应该知道,umi 中的命令可以直接创建一个文件夹,并以此链接到路由

还有就是在一个传统项目中,项目非常的庞大,我们如何剥离出项目,通过 cli 单独创立模块,从而进行更好的开发,这些功能都可以通过 cli 去实现,是不是瞬间觉得高大上了许多,哈哈哈哈~

还有什么功能,大家可以说说,我再去研究研究,摆脱下 low 这个字~

另外附上代码地址,供大家参观,如果有帮助,给个小小的Star,支持下~~

git 地址: domesy-cli

其他cli文章: 使用 cli,只需几秒就能出现一个模板?

其他好文: