小型脚手架工具搭建

开发一个脚手架工具

本文介绍开发一个脚手架流程。实现类似vue-cli的初始化项目的功能

  1. 初始化项目
执行npm init初始化一个项目

  1. 安装依赖包
包名用途
chalk控制台输出显示,比如加颜色啥的
commander命令行工具,有了它我们就可以读取命令行命令,知道用户想要做什么了
inquirer交互式命令行工具,给用户提供一个漂亮的界面和提出问题流的方式
download-git-repo下载远程模板工具,负责下载远程仓库的模板项目
ora用于显示加载中的效果,类似于前端页面的 loading 效果,像下载模板这种耗时的操作,有了 loading 效果可以提示用户正在进行中,请耐心等待
metalsmithcopy下载后的文件以及对文件做一些处理
  1. 设置脚手架命令

如下图所示:在项目的package.json文件增加bin属性配置命令,比如mkq-cli指向bin/mkq-cli.js 当我们输入命令mkq-cli的时候就会执行bin/mkq-cli.js。

{
  "name": "mkq-cli",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "bin": {
    "mkq-cli": "bin/mkq-cli.js",
    "mkq-cli-init": "bin/mkq-cli-init.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "chalk": "^4.1.1",
    "commander": "^8.0.0",
    "download-git-repo": "^3.0.2",
    "inquirer": "^8.1.2",
    "metalsmith": "^2.3.0",
    "ora": "^5.4.1"
  },
  "devDependencies": {
    "rimraf": "^3.0.2"
  }
}
  1. 编写脚手架功能
    如下是mkq-cli-init的实现
#!/usr/bin/env node   //此行表示node可执行该文件

const program = require("commander");
const chalk = require("chalk");
const download = require("download-git-repo");
const path = require("path");
const ora = require("ora");
const inquirer = require("inquirer");
const generate = require('../lib/generate-template')
/**
 * Usage.
 */

program
  .usage("<template-name> [project-name]")
  .option("-c, --clone", "use git clone");

/**
 * Help.
 */

program.on("--help", () => {
  console.log("  Examples:");
  console.log();
  console.log(
    chalk.gray("    # create a new project with an official template")
  );
  console.log("    $ vue init webpack my-project");
  console.log();
  console.log(
    chalk.gray("    # create a new project straight from a github template")
  );
  console.log("    $ vue init username/repo my-project");
  console.log();
});
/**
 * Help.
 */

function help() {
  program.parse(process.argv);
  if (program.args.length < 1) return program.help();
}
help();

/**
 * Settings.
 */

let template = program.args[0];
const hasSlash = template.indexOf("/") > -1;
const rawName = program.args[1];
const inPlace = !rawName || rawName === ".";
const name = inPlace ? path.relative("../", process.cwd()) : rawName;
const to = path.resolve(rawName || "test-pro");
const clone = program.clone || false;

const tmp = path.join(".vue-templates", template.replace(/[\/:]/g, "-"));
if (program.offline) {
  console.log(`> Use cached template at ${chalk.yellow(tildify(tmp))}`);
  template = tmp;
}
const question = [
  {
    name: "name",
    message: "请输入项目名称?",
  },
  {
    name: "author",
    message: "请输入作者?",
    when: (res) => Boolean(res.name),
  },
  {
    name: "description",
    message: "请输入项目描述?",
    when: (res) => Boolean(res.name),
  },
];

/**
 * Download a generate from a template repo.
 *
 * @param {String} template
 */
function run() {
  inquirer.prompt(question).then((answer) => {
    console.log(answer);
    downloadAndGenerate(template,{
      name:answer.name,
      author:answer.author,
      description:answer.description
    })
  });
}

run();
function downloadAndGenerate(template, conf) {
  const spinner = ora("downloading template");
  spinner.start();
  // Remove if local template exists
  // if (exists(tmp)) rm(tmp)
  download("github:mokq2016/my-ui#main", tmp, { clone }, (err) => {
    spinner.stop();
    console.log(err);
    //   if (err) logger.fatal('Failed to download repo ' + template + ': ' + err.message.trim())
    generate(name, tmp, to, conf, (err) => {
      console.log(err)
    });
  });
}

输入命令mkq-cli-init init newPro 之后就会执行该文件,运行run方法,通过inquirer插件与用户输入交互。得到用户输入,使用download下载github上的模板。然后通过generate生成项目

  1. 生成项目
var Metalsmith = require("metalsmith");
const rm = require('rimraf').sync

module.exports = function generate(name, src, dest,conf, done) {
  Metalsmith(process.cwd())
    .source(src)
    .destination(dest)
    .use((files, metalsmith, done) => {
      Object.keys(files).forEach(fileName => {
        //根据输入替换package.json内容
        if(fileName === 'package.json'){
          const t = files[fileName].contents.toString()
          const json = JSON.parse(t)
          Object.keys(conf).forEach(key=>{
            json[key] = conf[key]
          })
          files[fileName].contents = new Buffer(JSON.stringify(json),'utf8')
        }
      })
      done()
    })
    .build((err) => {
      rm('.vue-templates')
      done(err);
      if (!err) {
        console.log("success");
      } else {
        console.log(err);
      }
    });
};

这样便实现了一个小型脚手架初始化项目的功能。在开发时,可通过npm link把项目链接到全局模块,这样我们就可以测试我们的命令了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值