Node專案模板管理腳手架ptm-cli開發
一、ptm-cli 使用說明
project template manager cli
一款對專案模板/專案進行管理的腳手架工具,具有新增模板/專案
、編輯模板/專案
、刪除模板/專案
、檢視模板/專案
以及下載專案
和根據模板初始化專案
等功能。
1、特點
-
ptm-cli相容
github
和gitee碼雲
:現在很多自行開發的腳手架都是都只能對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) [email protected]:goodloving/vpblogs.git
? 請輸入模板分支(預設master) master
? 是否刪除模板中.git資訊(預設刪除) true
? 請輸入模板描述(預設為空) 基於vuepress建立個人部落格主頁的模板工程
新增模板成功!
最終的模板列表為:
vpblogs
url:[email protected]:goodloving/vpblogs.git
branch:master
description:基於vuepress建立個人部落格主頁的模板工程
delGitInfo:true
xxx %
3)編輯模板/專案
輸入命令:
$ ptm-edit templateName key content
根據終端提示輸入相關資訊:
templateName:本人
新增過的模板/專案名
;key:想要進行編輯的模板/專案的
關鍵資訊
,包括:url、branch、delGitInfo、description;content:對關鍵字對應
內容進行編輯替代
的內容;
例子(修改模板vpblogs的delGitInfo資訊):
xxx % ptm-edit vpblogs delGitInfo false
修改模板成功!
最終的模板列表為:
vpblogs
url:[email protected]:goodloving/vpblogs.git
branch:master
description:基於vuepress建立個人部落格主頁的模板工程
delGitInfo:false
xxx %
4)檢視模板/專案
輸入命令:
$ ptm-list
例子:
xxx % ptm-list
模板列表為:
vpblogs
url:[email protected]: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);
- ···
2)inquirer
處理可互動
的node.js嵌入式的命令列介面
的第三方npm庫。
常用API:
- 宣告 inquirer 變數
const inquirer = require('inquirer');
- 具體使用方式
inquirer
.prompt([
/* 放入可互動式提供的問題 */
])
.then(answers => {
// 命令列中接收到的輸入引數
})
.catch(error => {
// 報錯獲取
});
- ···
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: 切換到當前分支(可選).
4)chalk
改變終端輸出樣式
的第三方npm庫。
常用API:
- 宣告 chalk 變數
const chalk = require('chalk');
- 具體使用方式
console.log(chalk.blue('Hello world!'));
5)ora
新增優雅的終端轉輪
的第三方npm庫。
常用API:
- 宣告 ora 變數
const ora = require('ora');
- 具體使用方式
const spinner = ora('提示內容···');
- 開始顯示轉輪
spinner.start()
- 錯誤/失敗顯示轉輪
spinner.fail()
- 成功轉輪顯示
spinner.succeed()
- ···
6)rimraf
封裝rm -rf
命令,用來刪除檔案和資料夾
的第三方npm庫。
常用API:
- 宣告 rimraf 變數
const rm = require("rimraf").sync;
- 具體使用方式,刪除指定file檔案/資料夾
rm(file, [opts], callback)
- ···
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": "[email protected]"
},
"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包,安裝完執行自定義命令有效!