面试官:请简述一下vue-cli命令行工具,你能自己手写一个吗?

还记得我们在写vue 项目的时候用脚手架vue-init的主要作用是根据指定模板生成项目原型嘛?那么vue-init怎么实现的呢? 其实就是在vue-cli package.json中增加下面的代码

{
  "bin": {
    "vue": "bin/vue",
    "vue-init": "bin/vue-init",   //执行vue-init 的时候下载项目原型
    "vue-list": "bin/vue-list",
    "vue-build": "bin/vue-build"
  }
}

复制代码

具体实现请看下面:

本篇的主要内容是:实现可以在命令行中,直接运行代码(下面的名字可以自己取)。

xl-cli install (安装)
复制代码

在实现自己的命令行运行代码前,你需要对命令行,npm(包管理器)的基本用法有些了解。 下面进入正题:

//创建一个 xl-cli文件夹 mkdir xl-cli
// cd xl-cli 
// npm init  初始化
复制代码

完成上面几个步骤之后 我们能看到生成了一个xl-cli文件夹 文件中包含一个package.json文件。

{
  "name": "xl-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}
复制代码

我们知道在npm run xxx的时候其实就是执行的package.json中的scripts,比如上面 你看看npm run test就会输出Error: no test specified,我们的代码用的es6需要编译成es5,先创建一个npm run compile,(test没用,同时给test删掉)

{
  "name": "xl-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "compile": "babel src -d dist"
  },
  "author": "",
  "license": "ISC"
}
复制代码

我们需要安装babel 创建 (安装babel-cli babel-env)

src 
    --main.js
复制代码

这个时候我们执行 npm run compile其实就是相当于在命令行中输入了 babel src -d dist 然后我们看到了生成了一个这样的目录:

dist
    --main.js
复制代码

我们经常会有这样的需求就是在更改src 里面的内容的时候 同步更改dist里面的内容,可以这样做:在package.json的scripts增加一个 watch命令:

{
  "name": "xl-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "compile": "babel src -d dist",
    "watch":"npm run compile -- --watch"
  },
  "author": "",
  "license": "ISC"
}
复制代码

然后运行 npm run watch命令 就实现了同步更新了!

下面实现 xl-cli命令行

创建 ./bin/www目录, 要实现在命令行中使用 类似vue-cli这样的命令 需要在package.json中增加

"bin": {
    "xl-cli": "./bin/www"
  },
复制代码

./bin/www中的内容:

#! /usr/bin/env node

require('../dist/main.js');
复制代码

第一行 最后的node是表示node环境 前面参数写死的,第二行表示执行的代码 ,创建完成后执行npm link,相当于在本地添加环境变量。 至此,你已经可以执行xl-cli命令了,其实就是执行了dist/main.js。

实现像其他命令行中的xl-cli --help 先引入一个包 commander ,这个包可以帮助我们设置和解析命令参数。 src/main.js

//main.js
import program from 'commander';

import {VERSION} from './utils/constants';

program.command('install')                            //加命令 
        .description('install template')
        .alias('i')
        .action(() => {
            console.log('用户install了')
        })

program.version(VERSION,'-v --version').parse(process.argv);  //加 option
复制代码

我们可以看到在命令窗口输入 xl-cli install 会打印出:

用户install了
复制代码

好了 到现在我们就剩下执行下载模板任务了,这样我们新建一个install.js来执行下载任务

//install.js
import ora from 'ora';   //ora 一个命令行loading效果
import inquirer from 'inquirer'  //命令行交互
import downLoadGit from 'download-git-repo';  //github api用来下载github的模板

let install = async () => {
    // 下载模板 
    let loading = ora('fetching template......');
    let answer = await inquirer.prompt([
        {
            type: 'input',        //你可以输入你自己的名称
            name: 'projectName',
            message:'项目名称',
            default:'xlDemo'    //默认名
        }
    ]);
    // 项目名字
    let project = answer.projectName;
    loading.start();
    //我在github上面上传了一个非常简单的模板 xlei1123/xl-cli downLoadGit(src, dest)  从哪拉 拉到那  process.cwd()+'/'+project这是拉到了当前目录下的你刚刚命名的文件中
    downLoadGit('xlei1123/xl-cli',process.cwd()+'/'+project,(err) => {  
        if(err) {
            console.log(err)
            return;
        }
        console.log(process.cwd()+'/'+project)
        loading.succeed();
    });
}
export default install;
复制代码

这样在上面的action中执行 install()就好了!

//main.js
import program from 'commander';
import {VERSION} from './utils/constants';

import install from './install'
program.command('install')                            //加命令 
        .description('install template')
        .alias('i')
        .action(() => {
            install()
        })

program.version(VERSION,'-v --version').parse(process.argv);  //加 option
复制代码

这样我们就完成了自己cli了,可以执行下面几个简单的命令看一下效果:

xl-cli --help
xl-cli -v
xl-cli install
复制代码

一句话总结:我们发布了一个npm包 这个包的package.json中有bin可以全局执行,判断参数有install,就从github上面拉取模板。

当然这篇实现的是简单的命令行工具主要是理解其中大致原理,肯定会存在很多不足的地方,欢迎各位提出宝贵的意见或建议,也希望能帮助到你从中获得一些知识!

猜你喜欢

转载自juejin.im/post/5b4168bf6fb9a04f83462f6c