前言
這裡先簡單瞭解一下基礎知識,接下來會基於typescript和rollup參考寫一個較為完整的腳手架(動態模板),以下只能拉取較為簡單的靜態模板。
基礎
腳手架釋出和安裝
這裡假設我們的腳手架名字是ds-cli,以下都用這個名字。我們在命令列使用腳手架命令為ds
- 我們怎麼樣讓使用者通過npm或者yarn全域性安裝ds-cli之後,在終端能執行ds命令呢?答案就在package.json的bin欄位
- 當我們bin欄位指向我們的目標檔案main.js,同時目標檔案開頭具有
//這裡是main.js
#!/usr/bin/env node
// --這種用法是為了防止作業系統使用者沒有將node裝在預設的/usr/bin路徑裡。當系統看到這一行的時候,
// 首先會到env設定裡查詢node的安裝路徑,再呼叫對應路徑下的直譯器程式完成操作。
//這裡是package.json
"bin": {
"ds": "./main.js"
}
複製程式碼
- 這樣當我們釋出上npm,別人下載下來後,就可以直接使用ds命令了。
解析命令列
- 如何輕鬆便捷的讀取命令列裡的引數呢?這裡我們使用tj大神的commander
const cmd = require("commander");
// 比如我們想執行ds init **的命令,想出現“初始化元件模板”的描述
// action是執行這個命令後續的回撥,...args是後面**的引數
cmd
.command('init')
.description('初始化元件模板')
.action((...args) => {});
//解析命令列
cmd.parse(process.argv);
複製程式碼
使用者互動
我們通過詢問使用者來獲得一定的互動,這樣可以知道使用者需要什麼
- 採用inquirer詢問專案描述,作者
//比如我們在上面那個action裡面搞事情,即ds init之後問使用者
...action((...args)=>{
inquirer
.prompt([
{
name: "description",
message: "請輸入專案描述"
},
{
name: "author",
message: "請輸入作者名稱"
}
]).then(answers=>{
//在這裡獲得上面的答案
console.log(answers.description,answers.author)
})
})
複製程式碼
拉取遠端的倉庫
- download-git-repo可拉取遠端倉庫
const download = require("download-git-repo");
// 第一個git地址,第二個name是git clone下來後的名字...
download(
"https://github.com/yokiyokiyoki/vue-fullpage.git#master",
name,
{ clone: true },
err => {
...
}
);
複製程式碼
簡單的模板替換
- 我們通過詢問互動後,肯定內部做了些改變。這裡我們可以把package.json的作者和描述簡單改了
- 可以使用handlebars,模板語法簡單
//這個是通過download-git-repo拉下來的package.json
{
"author":"{{author}}",
"description":"{{description}}"
}
複製程式碼
- 然後我們通過讀取檔案字串給handbars編譯一下拿到的變數,再寫入
//通過詢問拿到的answers
const meta = {
name,
description: answers.description,
author: answers.author
};
const fileName = `${name}/package.json`;
//判斷一下是否有這個檔案
if (fs.existsSync(fileName)) {
const content = fs.readFileSync(fileName).toString();
const result = handlebars.compile(content)(meta);
fs.writeFileSync(fileName, result);
}
複製程式碼
終端的一些效果
const spinner = ora("正在下載模板...");
spinner.start();
spinner.succeed();
複製程式碼
- 列印日誌的特殊標誌:log-symbols
原始碼
#!/usr/bin/env node
// --這種用法是為了防止作業系統使用者沒有將node裝在預設的/usr/bin路徑裡。當系統看到這一行的時候,
// 首先會到env設定裡查詢node的安裝路徑,再呼叫對應路徑下的直譯器程式完成操作。
const program = require("commander");
const download = require("download-git-repo");
const inquirer = require("inquirer");
const handlebars = require("handlebars");
const fs = require("fs");
const ora = require("ora");
const chalk = require("chalk");
const symbols = require("log-symbols");
program
.version("0.0.1", "-v, --version")
.command("init <name>")
.action(name => {
if (fs.existsSync(name)) {
// 錯誤提示專案已存在,避免覆蓋原有專案
console.log(symbols.error, chalk.red("專案已存在"));
return;
}
inquirer
.prompt([
{
name: "description",
message: "請輸入專案描述"
},
{
name: "author",
message: "請輸入作者名稱"
}
])
.then(answers => {
download(
"https://git.datatub.com:Uranus/general-template#master",
name,
{ clone: true },
err => {
const spinner = ora("正在下載模板...");
spinner.start();
if (!err) {
spinner.succeed();
const meta = {
name,
description: answers.description,
author: answers.author
};
const fileName = `${name}/package.json`;
if (fs.existsSync(fileName)) {
const content = fs.readFileSync(fileName).toString();
const result = handlebars.compile(content)(meta);
fs.writeFileSync(fileName, result);
}
console.log(symbols.success, chalk.green("專案初始化完成"));
} else {
spinner.fail();
console.log(symbols.error, chalk.red(`拉取遠端倉庫失敗${err}`));
}
}
);
});
});
//解析命令列
program.parse(process.argv);
複製程式碼
- 上面是main.js檔案,然後修改一下package.json的欄位(bin欄位修改,模板變數)
- 釋出npm(如何釋出,請參考這裡),自己通過npm全域性下載之後體驗一下