準備工作
1. 創建工程
mkdir my-clicd my-clinpm init -ynpm i commander download-git-repo ora handlebars figlet clear chalk open watch -S複製代碼2. 創建 bin 目錄
package.json 添加 bin 欄位,將自定義的命令軟連到全局環境,同時執行 npm link 創建連結。"bin": { "wbiao": "./bin//index.js" }複製代碼在根目錄下創建 bin 文件夾,新建 index.js 文件,行首增加一行#!/usr/bin/env node指定當前腳本由 node.js 進行解析。#!/usr/bin/env nodeconsole.log("Hello World!!!");複製代碼命令行執行npm link,相當於把這個包連接到全局。如果 npm link 報錯,windows/mac 嘗試使用管理員身份輸入。
在命令行執行wbiao
2. 搭建命令行界面
識別命令行 - commander
command 後面可跟一個 name,用空格隔開。
alias: 定義一個更短的命令行指令description:描述,他在 help 裡展示action:註冊一個回調函數parse:解析命令行const program = require("commander");program.version(require("../package.json").version);program .command("init <name>") .alias("i") .description("init project") .action((name) => {console.log(`項目名稱為:${name}`); });// 解析主進程的參數program.parse(process.argv);複製代碼輸出歡迎界面 - figlet/clear/chalk
輸入 wbiao init 就會輸出以下歡迎界面,那麼需要什麼工具?
工具:
figlet: 創建字符圖案clear: 清屏chalk: 改變 log 顏色的工具做法:
新建文件夾 lib,新建 init.jsconst { promisify } = require("util");const figlet = promisify(require("figlet")); // 字符畫const clear = require("clear"); // 清屏const chalk = require("chalk"); // 改變輸出log顏色的工具const log = (content) => console.log(chalk.green(content)); // 封裝consolemodule.exports = async (name) => { clear();// 輸出歡迎界面const figlet_data = await figlet("WBIAO"); log(figlet_data);};複製代碼加載進度 - ora
asyncfunctionclone(repo, desc) {const download = promisify(require("download-git-repo")); // 從git下載倉庫const ora = require("ora"); // 命令行顯示加載效果const process = ora(`downing ${repo}....`); process.start();await download(repo, desc); process.succeed();}複製代碼從 git 下載倉庫 - download-git-repo / ora
download-git-repo 有一個 clone 方法,用法如下:
clone(repository, destination, options, callback);複製代碼
在下載倉庫的過程中需要添加加載的過程,可以使用 ora 庫。
const ora = require("ora");const spinner = ora("Loading unicorns").start();setTimeout(() => { spinner.color = "yellow"; spinner.text = "Loading rainbows";}, 1000);複製代碼顯示的效果是:
此時我們封裝一個 download 方法,用作下載倉庫並顯示進度
asyncfunctionclone(repo, desc) {const download = promisify(require("download-git-repo")); // 從git下載倉庫const ora = require("ora"); // 命令行顯示加載效果const process = ora(`downloading ${repo}....`); process.start();await download(repo, desc); process.succeed();}複製代碼在 init 裡引入
module.exports = async (name) => { ...// 2. 下載項目 log("創建項目:" + name);await clone("github:hopkinson/vue-mock-demo", name);};複製代碼選取模板下載倉庫 - inquirer
我們如果有多個模板的情況下需要選擇一個,那就不能寫固定下載地址,而是根據需要選擇模板。那麼可以用 inquirer 庫。
基本用法:
const inquirer = require("inquirer");const promptList = [ { type: "list", name: "type", message: "請選擇拉取的模板類型: ", choices: [ { name: "pc", value: { url: "hopkinson/vue-mock-demo", gitName: "vue-mock-demo", val: "PC端模版", }, }, ], },];inquirer.prompt(promptList).then((answers) => {console.log(answers); // 返回的結果});複製代碼在腳手架裡,在 init 裡引入選擇模板並下載:
var promptList = [ { type: "list", name: "type", message: "請選擇拉取的模板類型: ", choices: [ { name: "pc", value: { url: "hopkinson/vue-mock-demo", gitName: "vue-mock-demo", val: "PC端模版", }, }, { name: "mobile", value: { url: "littleTreeme/vue-web-template.git", gitName: "vue-web-template", val: "PC端模版", }, }, ], },];inquirer.prompt(promptList).then(async (result) => {const { url, gitName, val } = result.type;await clone(`github:${url}`, name); log(`已下載${gitName}(${val})項目,正在安裝依賴...`);});複製代碼3. 安裝依賴 - spawn
封裝 spawn 函數,通過子線程來做我們的安裝依賴;
const spawn = async (...args) => {const { spawn } = require("child_process"); //原生包的子進程returnnewPromise((resolve) => {const proc = spawn(...args); proc.stdout.pipe(process.stdout); //子進程的輸出流與主進程相對接 為了列印子進程的日誌 proc.stderr.pipe(process.stderr); //錯誤流 proc.on("close", () => { resolve(); }); });};複製代碼然後再引入到 init 裡。
注意的是:window10 中,在 spawn 中執行 npm 報錯 [Error: spawn ENOENT]」 errors。解決方法是:加入的判斷process.platform === "win32" ? "npm.cmd" : "npm"
module.exports = async (name) => { ...// 3. 自動安裝依賴//npm:要執行的命令,可以是cnpm...// * []:所有參數放數組中// * cwd: 在哪個目錄下執行命令 spawn(process.platform === "win32" ? "npm.cmd" : "npm", ["install"], { cwd: `./${name}` }); log(` 安裝完成: ============== cd ${name} npm run dev ============== `);};複製代碼4. 自動啟動界面 -open
open: 打開瀏覽器module.exports = async (name) => { ...// 4.打開瀏覽器await spawn( process.platform === "win32" ? "npm.cmd" : "npm", ["run", "dev"], { cwd: `./${name}` } ); open("http://localhost:8080");};複製代碼