简易的脚手架搭建

107 阅读7分钟

前言

当我们在接手到某一个项目时,总是得先去初始化项目。对于项目的初始化而言,很多都是重复的,我们再去初始化一遍其实也是没有必要的。我们换个思路想想,每次我们创建vue项目的时候,我们都是通过命令行直接输指令就可以快速的创建vue项目。这样通过命令创建项目,就是vue-cli来帮助我们创建的。我们也称vue-cli为vue脚手架。

像这样可以帮助我们快速创建项目的,就是脚手架。

所用到的插件

脚手架创建项目都是在命令行里输入命令然后根据命令进行创建的。所以我们就需要能在命令行中进行交互,当然我们也没那么大能耐可以写一个命令行交互。这里我们就需要用到我们的第一个插件——commander.js

commander.js

我们这里就简单讲解一下commander.js的使用方法

安装

npm install commander
&&
yarn add commander

我们先写一个demo来看看

const { program } = require("commander");

program
  .option("-n", "输出名称", '123')
  .option("-t --type <type>", "项目类型")
  .option("-a [test]", "test")

program.parse();

const options = program.opts();
console.log("options", options);

我们先从commander引入program

然后就可以用 .option的方式来创建option

.option('-n, --name [p2]', '描述', '默认值')

  • n和name分别是短长定义(可以认为n是name的简写);

  • p代表选项后面跟着的参数,< >必填,[ ]选填,不填默认是布尔值;

  • 最后两个参数分别是描述文案和选项的默认值

创建完成之后我们一定要调用一下**program.parse()**来解析program,不然我们是没有办法获取到参数的。

我们可以先用-h来查看可以输入的option:

image.png 这里可以看到我们定义的option在这里都有提示,并且描述也有输出

那我们现在来尝试调用一下:

image.png

这里可以看到直接用-n调用时,我们-n命令是没有任何参数的并且这里虽然定义了默认值,但是还是出的布尔值。我们在后面其他调用时n就会是我们定义的默认值并且一同输出。

我们在-a这里定义的参数是选填,我们可以从上面的输出的结果看,如果我们不填输出就是布尔值,填了之后才是我们填的参数。


接下来我们来讲一下命令的创建 命令command: 使用格式

  • command('add [params]')
  • description('描述')
  • alias('简称')
  • action(function(){ }) //命令处理函数
const { program } = require("commander");

program
  .command("create <app-name>")
  .description("创建一个标准的vue项目")
  .alias('c')
  .action((name) => {
    console.log("正在创建vue项目,名称为:" + name);
  });

program.parse();

image.png 后面我们创建脚手架里主要的操作都会在action里面来进行

注意

我们定义option必须在写在命令后面才能执行

image.png

补充:

这里还可以使用program.version("0.0.1")来指定版本

image.png

figlet

figlet 是一个在终端输出大型文字的插件

使用格式:

figlet(String, callback)

  • String: 要输出的字符
  • callback:解析字符的回调
let figlet = require('figlet')
    
figlet("Hello World!!", function (err, data) {
  if (err) {
    console.log("Something went wrong...");
    console.dir(err);
    return;
  }
  console.log(data);
});

image.png 如果不喜欢callback的调用,我们可以使用nodeJs自带的util库中的promisify将一个对象包装成promise结构

let asyncfiglet = promisify(require("figlet"));

async function run() {
  try {
    let data = await asyncfiglet("Vue 3");
    console.log(data);
  } catch (error) {
    console.log(error);
  }
}

run();

image.png

chalk

chalk 可以美化我们的输出内容 因为比较简单,我们这里直接展示一下用法:

let chalk = require("chalk");

console.log(chalk.blue('Hello world!'));

注意:

现在chalk默认下载是5.1.2的版本,他的引入使用的是import的node中是使用CommanJs的模块化规范,想要使用require语法得下载4.1.0的版本

image.png

ora

ora 是一个用来输出loading状态的插件,它的使用也很简单,我们这里也简单介绍一下就行了

const ora = require("ora");

// 创建loading对象,ora的内容就是文字内容,调用start在控制台中开始loading
const spinner = ora("Loading unicorns").start();

setTimeout(() => {
  // 将loading的颜色变为黄色
  spinner.color = "yellow";
  // 修改loading的文字
  spinner.text = "Loading rainbows";
  setTimeout(() => {
    // 雕用stop停止
    spinner.stop();
  }, 1000);
}, 2000);

image.png 两秒后颜色文字变化

image.png 然后再过一秒停止

inquirer

inquirer:命令行参数输入交互

注意下载8.0.0** 的版本才能使用require

const inquirer = require("inquirer");

inquirer
  .prompt([
    {
      name: "userName",
      type: "input",
      message: "你的名字是",
    },
    {
      name: "age",
      type: "checkbox",
      message: "你多大了?",
      choices: ["20-25", "25-30", "30-40", "40以上"],
    },
    {
      name: 'salary',
      type: 'list',
      message: '你的薪资是多少?',
      choices: ["10k-20k", '20k-30k', '30k-40k']
    }
  ])
  .then((answer) => {
    console.log("回答内容:", answer);
  });

使用也很简单,pormpt中传入的数组中的每一项都是每一个问题的配置这里列举了三个最常用的类型

  • input: 从控制台输入
  • checkbox: 多选框,用空格来选择,选项在choies中配置
  • list: 单选,直接回车选择,选项也在choies中配置

结果在.then的调用中传递,我们这里也能看出来它是一个promise所以我们也是可以使用async/await的方式来获取结果的

image.png

download-git-repo

download-git-repo 可以帮助我们从git上面下载项目到本地,用法也很简单,这里简单介绍一下,具体的效果在后面演示 使用格式:

download("url", "name", { 配置 } function (err) { console.log(err ? "Error" : "Success"); });

  • url: 仓库地址
  • name: 下载下来之后放进的文件夹的名字
  • 配置:
    • { clone: true }:是否直接克隆
    • { headers: { 'PRIVATE-TOKEN': '1234' } }:使用具有自定义源和令牌的 GitLab 存储库中的 http 下载
  • callback:失败后的回调

这里所用到的插件差不多都介绍完了,接下来创建脚手架无非就是对这些插件的调用了。

脚手架创建

我们先来分析一下大致流程:

流程无非就是创建一个命令行交互,进行一些参数选择。然后根据选择参数进行不同的操作,然后把我们通用初始化的项目从git上拉取下来。

流程很短,我们直接上代码:

//index.js
/**
 * 开发后台脚手架,快速生成标准Vue后台架构
 * @author 刚睡醒的番茄
 */
let program = require("commander");
let { promisify } = require("util");
let asyncFiglet = promisify(require("figlet"));
let chalk = require("chalk");
let inquirer = require("inquirer");
// 手动编写的初始化方法
let init = require('./init')

// 日志打印函数
const log = (content) => console.log(chalk.yellow(content));

// 设置版本和参数
program.version("1.0.0");
program.option("-n --name <type>", "output name");

// 打印LOGO
async function printLogo() {
  let data = await asyncFiglet("v-cli");
  log(data);
}

program
  .command("create <app-name>")
  .description("创建Vue项目")
  .action(async (name) => {
    await printLogo();
    log("准备创建项目...");
    let answer = await inquirer.prompt([
      {
        name: "language",
        type: "list",
        message: "请选择语言版本",
        choices: ["Javascript", "Typescript"],
      },
    ]);
    if (answer.language == "Javascript") {
      // 下载框架
      log('您选择了Javascript版本,即将进入下载模式.')
      init(name)
    } else {
      log("敬请期待!")
    }
  });

// 参数解析
program.parse();

无非就是对上面的插件进行使用,init方法就是我单独封装的方法,用来从git上克隆项目。

// init.js
/**
 * 项目克隆
 */
let { promisify } = require("util");
const ora = require("ora");
const download = promisify(require("download-git-repo"))
const shell = require("shelljs");
let chalk = require("chalk");

// 日志打印函数
const log = (content) => console.log(chalk.yellow(content));

module.exports = async (appName) => {
  log(`🚀创建项目${appName}`);
  shell.rm('-rf', appName)
  const spinner = ora("下载中...").start();
  try {
    await download(
      "direct:https://gitee.com/chenwing_gum/YC-manager.git",
      appName,
      { clone: true }
    );
    spinner.succeed("下载完成")
    log(`
      下载完成,请执行下面命令启动项目:
      =============================
      cd ${appName}
      yarn || npm install
      yarn dev || npm run dev
    `)
  } catch (error) {
    log(`下载失败`, error);
    spinner.stop()
  }
};

这里我又引入了shellJs这是当我们已经下载了文件,如果我们重复下载了并且命名相同,为了防止报错使用Shell.rm(-rf, 文件名)来删除文件的。还有一点,我们这里把download-git-repo封装成了Promise结构。 实际效果:

image.png

image.png

image.png

image.png 这里我们看到,我们在v-cli目录下执行了creat指令创建名为vue-1的项目,成功在v-cli目录下创建了。这里注意一点vue-1项目的创建位置跟我们输入指令的位置相关。

总结

我们不难看出来,我这个脚手架的创建还是非常简单的,基本上就是各种插件的调用,没啥含金量。所以也反应出来一点,创建脚手架好像听起来很高大上,但是我们从最简单的入手好像也没有那么的困难。所以,勇于尝试一些自己害怕的事情,从最简单的开始,慢慢来。