关于前端:项目模板管理脚手架ptmcli开发

一、ptm-cli 应用阐明

  project template manager cli

  一款对我的项目模板/我的项目进行治理的脚手架工具,具备增加模板/我的项目编辑模板/我的项目删除模板/我的项目查看模板/我的项目以及下载我的项目依据模板初始化我的项目等性能。

1、特点

  • ptm-cli兼容githubgitee码云

    当初很多自行开发的脚手架都是都只能对github上模板/我的项目进行下载(底层应用download-git-repo),随着国内码云的发展壮大,国内开发者很多也在码云上进行代码治理,兼容gitee也十分必要;目前现有的脚手架轮子中并没有兼容码云的!

  • 治理性能全

    大多数脚手架只对某一个模板进行初始化下载,只具备指定初始化性能;ptm-cli可能对模板和我的项目进行治理,不仅能够自由增加删除开源的优良我的项目(例如vue),还能够增加删除编辑本人开发的我的项目模板

2、装置

$ npm install ptm-cli -g

3、应用

1)根底帮忙命令

装置完在电脑终端输出相应命令查看和执行相干操作。

# 查看脚手架可执行的相干命令语句
$ ptm 

# 查看以后版本
$ ptm -V

# 查看帮忙
$ ptm -h

2)增加模板/我的项目

输出命令:

$ ptm-add

依据终端提醒输出相干信息:

模板名:增加的模板自定义命名(倡议应用引文);

url:模板/我的项目在github或者码云上的https/ssh克隆地址链接;

branch:模板/我的项目所在github或者码云上的分支名(默认master);

delGitInfo是否删除模板/我的项目中的原作者git的开发信息(默认true删除),对于模板治理倡议默认设置为true,即初始化模板不含有其余让人的git信息,对于项目管理(本人我的项目)倡议保留本人开发相干的git信息;

description:模板/我的项目的形容信息(默认为空);

例子:

xxx % ptm-add  
? 请输出模板名称 vpblogs
? 请输出模板地址(https/ssh) git@gitee.com:goodloving/vpblogs.git
? 请输出模板分支(默认master) master
? 是否删除模板中.git信息(默认删除) true
? 请输出模板形容(默认为空) 基于vuepress创立集体博客主页的模板工程

增加模板胜利!

最终的模板列表为:
   vpblogs
     url:git@gitee.com:goodloving/vpblogs.git
     branch:master
     description:基于vuepress创立集体博客主页的模板工程
     delGitInfo:true
xxx % 

3)编辑模板/我的项目

输出命令:

$ ptm-edit templateName key content

依据终端提醒输出相干信息:

templateName:自己增加过的模板/我的项目名

key:想要进行编辑的模板/我的项目的要害信息,包含:urlbranchdelGitInfodescription

content:对关键字对应内容进行编辑代替的内容;

例子(批改模板vpblogs的delGitInfo信息):

xxx % ptm-edit vpblogs delGitInfo false

批改模板胜利!

最终的模板列表为:
   vpblogs
     url:git@gitee.com:goodloving/vpblogs.git
     branch:master
     description:基于vuepress创立集体博客主页的模板工程
     delGitInfo:false
xxx % 

4)查看模板/我的项目

输出命令:

$ ptm-list

例子:

xxx % ptm-list

模板列表为:
   vpblogs
     url:git@gitee.com:goodloving/vpblogs.git
     branch:master
     description:基于vuepress创立集体博客主页的模板工程
     delGitInfo:false
xxx % 

5)删除模板/我的项目

输出命令:

$ ptm-del

例子:

xxx % ptm-del
? 请输出要删除的模板名称 vpblogs

删除模板胜利!

最终的模板列表为:
xxx % 

6)基于模板新建/初始化我的项目

输出命令:

$ ptm-init vpblogs testPTM

例子(依据模板vpblogs新建我的项目testPTM):

xxx % ptm-init vpblogs testPTM

开始创立我的项目~ 

✔ 正在创立中···

我的项目创立胜利~ 

开始你的我的项目开发!
xxx % 

执行实现后在以后终端所在目录下能够看到名为testPTM的我的项目文件!

ptm-cli 脚手架开发

1、常识储备

1)commander

残缺的 node.js 命令行解决方案,用来解决终端命令行中输出命令和编写命令行指令的第三方npm库。

罕用API:

  • 申明 program 变量

const { program } = require(‘commander’);

  • 命令行输入版本号

program.version(‘0.0.1’);

  • 命令行输入指令提醒

program.usage(“\<command> [Options]”);

  • 命令行输入繁多命令输出标准提醒

program.command(“ptm-add”, “新增一个模板库!”)

  • 解析命令行参数

program.parse(process.argv);

  • ···

commander具体api

2)inquirer

解决可交互的node.js嵌入式的命令行界面的第三方npm库。

罕用API:

  • 申明 inquirer 变量

const inquirer = require(‘inquirer’);

  • 具体应用形式

inquirer
.prompt([
/ 放入可交互式提供的问题 /
])
.then(answers => {
// 命令行中接管到的输出参数
})
.catch(error => {
// 报错获取
});

  • ···

inquirer具体api

3)git-clone

通过shell命令克隆一个git存储库的第三方npm库。

罕用API:

  • 申明 git-clone 变量

const clone = require(‘git-clone’);

  • 具体应用形式

clone(repo, targetPath, [options], cb);
克隆一个repo门路的git仓库到targetPath目录下,回调函数cd用来捕获克隆后果;

  • options可选参数:
  • git: git的二进制门路(可选).
  • shallow: 当为true时克隆深度为1 (可选).
  • checkout: 切换到以后分支(可选).

git-clone具体api

4)chalk

扭转终端输入款式的第三方npm库。

罕用API:

  • 申明 chalk 变量

const chalk = require(‘chalk’);

  • 具体应用形式

console.log(chalk.blue(‘Hello world!’));

chalk具体api

5)ora

增加优雅的终端转轮的第三方npm库。

罕用API:

  • 申明 ora 变量

const ora = require(‘ora’);

  • 具体应用形式

const spinner = ora(‘提醒内容···’);

  • 开始显示转轮

spinner.start()

  • 谬误/失败显示转轮

spinner.fail()

  • 胜利转轮显示

spinner.succeed()

  • ···

ora具体api

6)rimraf

封装rm -rf命令,用来删除文件和文件夹的第三方npm库。

罕用API:

  • 申明 rimraf 变量

const rm = require(“rimraf”).sync;

  • 具体应用形式,删除指定file文件/文件夹

rm(file, [opts], callback)

  • ···

rimraf具体api

2、初始化我的项目

  新建我的项目文件夹PTM_CLI,在我的项目文件夹下关上终端执行初始化操作npm init,与终端进行交互操作生成含有我的项目信息的package.json文件,顺次装置步骤1中的6个要用到的第三方npm库:npm install xxx -g(也可间接将依赖写入package.json中的dependences中,间接执行npm install);
  关上package.json文件,增加终端命令执行语句(bin区域下):

{
  "name": "ptm-cli",
  ···
  "private": false,
  "author": {
    "name": "wawoweb",
    "wechat(公众号)": "wawoweb  /  哇喔WEB",
    "wechat": "h17179797429",
    "email": "936106161@qq.com"
  },
  "bin": {
    "ptm": "./bin/ptm.js",
    "ptm-init": "./bin/ptm-init.js",
    "ptm-list": "./bin/ptm-list.js",
    "ptm-add": "./bin/ptm-add.js",
    "ptm-del": "./bin/ptm-del.js",
    "ptm-edit": "./bin/ptm-edit.js"
  },
 
  ···
  "dependencies": {
    "chalk": "^4.1.0",
    "commander": "^6.2.1",
    "git-clone": "^0.1.0",
    "inquirer": "^7.3.3",
    "ora": "^5.1.0",
    "rimraf": "^3.0.2"
  }
}

同时,在我的项目文件夹下新建目录bin,并在bin文件夹下新建package.json中对应的6个文件:

./bin/ptm.js         终端命令ptm执行文件
./bin/ptm-init.js     终端命令ptm-init执行文件(依据模板初始化我的项目)
./bin/ptm-list.js     终端命令ptm-list执行文件(查看以后模板列表)
./bin/ptm-add.js     终端命令ptm-add执行文件(增加新的模板)
./bin/ptm-del.js     终端命令ptm-del执行文件(删除指定模板)
./bin/ptm-edit.js     终端命令ptm-edit执行文件(编辑指定模板指定信息内容)

最初在根目录下新建模板存储文件template.json,我的项目目录构造如下:

3、性能开发

  在上述新建bin目录下的6个性能文件最上方增加#!/usr/bin/env node:配置#!/usr/bin/env node, 就是解决了不同零碎node门路不同,让零碎动静的去查找node来执行你的脚本文件。

1)ptm(脚手架命令提醒)

剖析:

  当用户不理解ptm-cli时,输出ptm能够向用户展现可用的所用命令语句和含意(commander);

代码(ptm.js):
#!/usr/bin/env node
const program = require("commander");
const package = require("../package.json");

// 定义以后版本
// 定义应用办法
// 定义五个指令
program
  .version(package.version)
  .usage("<command> [Options]")
  .command("ptm-add", "新增一个模板库!")
  .command("ptm-del", "删除一个模板库!")
  .command("ptm-list", "查看模板库列表!")
  .command("ptm-edit templatename key content", "批改模板库信息!")
  .command("ptm-init templatename projectName", "基于模板库创立一个新的工程!");

// 解析命令行参数
program.parse(process.argv);

2)ptm-add(增加模板)

剖析:

  将用户指定模板增加到template.json中存储起来,须要与用户进行交互(inquirer),波及到文件的读写(fs),将执行后果向用户展现(chalk);

代码(ptm-add.js):
#!/usr/bin/env node
//交互式命令行库
const inquirer = require("inquirer");
//控制台款式库
const chalk = require("chalk");
//node内置文件模块库
const fs = require("fs");
//读取模板配置文件
const tpConfig = require(`${__dirname}/../template.json`);
// 打印模板列表的公共函数
const printPtmList = require("../utils").printPtmList;

//自定义交互式命令行的问答
let questions = [
  {
    name: "name",
    type: "input",
    message: "请输出模板名称",
    validate(val) {
      if (val === "") {
        return "模板名不能为空!";
      } else if (tpConfig[val]) {
        return "模板名曾经存在!";
      } else {
        return true;
      }
    },
  },
  {
    name: "url",
    type: "input",
    message: "请输出模板地址(https/ssh)",
    validate(val) {
      if (val === "") return "模板地址不能为空!";
      return true;
    },
  },
  {
    name: "branch",
    type: "input",
    message: "请输出模板分支(默认master)",
    default: "master",
  },
  {
    name: "delGitInfo",
    type: "input",
    message: "是否删除模板中.git信息(默认删除)",
    default: true,
  },
  {
    name: "description",
    type: "input",
    message: "请输出模板形容(默认为空)",
    default: "",
  },
];

inquirer.prompt(questions).then((answers) => {
  // 获取用户输出的内容
  let { name, url, branch, description, delGitInfo } = answers;
  //过滤Unicode的字符
  tpConfig[name] = {
    url,
    branch,
    description,
    delGitInfo,
  };
  // 将模板信息写入template.json文件中s
  fs.writeFile(
    `${__dirname}/../template.json`,
    JSON.stringify(tpConfig),
    "utf-8",
    (err) => {
      if (err) {
        console.log(chalk.red(`\n增加模板失败:${err}\n`));
      } else {
        console.log(chalk.green("\n增加模板胜利!\n"));
        console.log("最终的模板列表为:");
        printPtmList(tpConfig);
      }
    }
  );
});

模板列表打印函数封装(utils.js):

const chalk = require("chalk");
const printPtmList = (tpConfig) => {
  //遍历模板展现进去
  for (const key in tpConfig) {
    if (tpConfig.hasOwnProperty(key)) {
      const item = tpConfig[key];
      console.log(chalk.blue(`   ${key}`));
      for (const i in item) {
        if (item.hasOwnProperty.call(item, i)) {
          const el = item[i];
          console.log(chalk.blue(`     ${i}:${el}`));
        }
      }
    }
  }
};
module.exports = {
  printPtmList
};

3)ptm-list、ptm-del、ptm-edit

剖析:
  • ptm-list:读取template.json文件(fs),对json格局数据输入打印(chalk);
  • ptm-del:读取template.json文件(fs),与用户交互(inquirer),删除指定模板信息,输入删除后后果(chalk)
  • ptm-edit:读取template.json文件(fs),与用户交互(inquirer),指定模板的信息进行批改(commander),输入最终批改后果(chalk);

代码简略(省略)

4)ptm-init(依据模板初始化我的项目)

剖析:

  提醒用户ptm-init命令必须的参数设置,对输出参数进行判断,读取template.json信息提取新建我的项目基于的模板信息,从github或者gitee(码云)clone git库文件,依据配置中要求判断是否删除原作者的git开发信息,输入init后果

代码

ptm-init.js

#!/usr/bin/env node
const program = require("commander");
const chalk = require("chalk");
const ora = require("ora");
const gitclone = require("git-clone");
const tpConfig = require(`${__dirname}/../template`);
const rm = require("rimraf").sync;

program.usage("templatename projectName").parse(process.argv);

//判断输出状况
if (program.args.length < 1) {
  return program.help();
}
//输出参数提取
let templateName = program.args[0];
let projectName = program.args[1];
//参数校验
if (!tpConfig[templateName]) {
  console.log(chalk.red("以后模板不存在!\n"));
  return;
}
if (!projectName) {
  console.log(chalk.red("新建我的项目名不能为空! \n"));
  return;
}

let temp = tpConfig[templateName];
//提取模板的url
let url = temp.url;
//提取分支
let branch = temp.branch;

console.log(chalk.greenBright("\n开始创立我的项目~ \n"));
//显示加载图标
const spinner = ora("正在创立中···");
spinner.start();

//下载所需额定参数
let cloneOptions = {
  checkout: branch,
  shallow: branch === "master",
};

// 下载git上模板代码
gitclone(url, projectName, cloneOptions, (err) => {
  if (err) {
    spinner.fail();
    console.log(chalk.red(`\n创立我的项目失败:${err}\n`));
  } else {
    if (temp.deldelGitInfo) {
      // 删除.git相干文件
      rm(projectName + "/.git");
    }

    //胜利
    spinner.succeed();
    console.log(chalk.green("\n我的项目创立胜利~ \n"));
    console.log(chalk.green("开始你的我的项目开发!"));
  }
});

4、npm公布

  • 1)确认package.json中npm公布内容是否欠缺正确

    • “name”: “ptm-cli”, //公布到npm上的库的名字
    • “version”: “1.0.0”, //以后公布版本号(x.y.z格局规定:x大的版本号,大版本号不同代表不向下兼容;y小版本号,以后版本较大改变,向下兼容;z代码较小改变或者bug批改)
    • “description”: “”, //npm库的简要形容
    • “private”: false, //是否公开设置
    • “keywords”: [], //npm上搜寻的关键词设置
    • ···
  • 2)npm登录和公布

    • 去npm网站注册账号;
    • 终端输出npm login,依据提醒输出用户名、明码、邮箱;
    • 终端输出npm publish 公布,查看后果是否公布胜利;
    • 强制撤回24小时内公布的npm库,输出npm unpublish --force
  • 3)npm公布验证

    • 在npm网站搜寻中输出公布的npm库名,可能搜寻到阐明曾经公布胜利!

    • 本地下载验证

    关上本地终端输出npm install ptm-cli -g 下载安装公布的npm包,装置完执行自定义命令无效!

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理