您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“如何開發(fā)一個(gè)Parcel-vue腳手架工具”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“如何開發(fā)一個(gè)Parcel-vue腳手架工具”這篇文章吧。
為什么需要需要腳手架?
減少重復(fù)性的工作,不再需要復(fù)制其他項(xiàng)目再刪除無關(guān)代碼,或者從零創(chuàng)建一個(gè)項(xiàng)目和文件。
根據(jù)交互動(dòng)態(tài)生成項(xiàng)目結(jié)構(gòu)和配置文件等。
多人協(xié)作更為方便,不需要把文件傳來傳去。
思路
要開發(fā)腳手架,首先要理清思路,腳手架是如何工作的?我們可以借鑒 vue-cli 的基本思路。vue-cli 是將項(xiàng)目模板放在 git 上,運(yùn)行的時(shí)候再根據(jù)用戶交互下載不同的模板,經(jīng)過模板引擎渲染出來,生成項(xiàng)目。這樣將模板和腳手架分離,就可以各自維護(hù),即使模板有變動(dòng),只需要上傳最新的模板即可,而不需要用戶去更新腳手架就可以生成最新的項(xiàng)目。那么就可以按照這個(gè)思路來進(jìn)行開發(fā)了。
第三方庫
首先來看看會(huì)用到哪些庫。
commander.js,可以自動(dòng)的解析命令和參數(shù),用于處理用戶輸入的命令。
download-git-repo,下載并提取 git 倉庫,用于下載項(xiàng)目模板。
Inquirer.js,通用的命令行用戶界面集合,用于和用戶進(jìn)行交互。
handlebars.js,模板引擎,將用戶提交的信息動(dòng)態(tài)填充到文件中。
ora,下載過程久的話,可以用于顯示下載中的動(dòng)畫效果。
chalk,可以給終端的字體加上顏色。
log-symbols,可以在終端上顯示出 √ 或 × 等的圖標(biāo)。
初始化項(xiàng)目
首先創(chuàng)建一個(gè)空項(xiàng)目,然后新建一個(gè) index.js 文件,再執(zhí)行 npm init 生成一個(gè) package.json 文件。最后安裝上面需要用到的依賴。
npm install commander download-git-repo inquirer handlebars ora chalk log-symbols -S
處理命令行
node.js 內(nèi)置了對(duì)命令行操作的支持,在 package.json 中的 bin 字段可以定義命令名和關(guān)聯(lián)的執(zhí)行文件。所以現(xiàn)在 package.json 中加上 bin 的內(nèi)容:
{ "name": "suporka-parcel-vue", "version": "1.0.0", "description": "a vue cli which use parcel to package object", "bin": { "suporka-parcel-vue": "index.js" }, ... }
然后在 index.js 中來定義 init 命令:
#!/usr/bin/env node const program = require('commander'); program.version('1.0.0', '-v, --version') .command('init <name>') .action((name) => { console.log(name); }); program.parse(process.argv);
調(diào)用 version('1.0.0', '-v, --version') 會(huì)將 -v 和 --version 添加到命令中,可以通過這些選項(xiàng)打印出版本號(hào)。
調(diào)用 command('init <name>') 定義 init 命令,name 則是必傳的參數(shù),為項(xiàng)目名。
action() 則是執(zhí)行 init 命令會(huì)發(fā)生的行為,要生成項(xiàng)目的過程就是在這里面執(zhí)行的,這里暫時(shí)只打印出 name。
其實(shí)到這里,已經(jīng)可以執(zhí)行 init 命令了。我們來測試一下,在同級(jí)目錄下執(zhí)行:
node index.js init HelloWorld
可以看到命令行工具也打印出了 HelloWorld,那么很清楚, action((name) => {}) 這里的參數(shù) name,就是我們執(zhí)行 init 命令時(shí)輸入的項(xiàng)目名稱。
命令已經(jīng)完成,接下來就要下載模板生成項(xiàng)目結(jié)構(gòu)了。
下載模板
download-git-repo 支持從 Github、Gitlab 和 Bitbucket 下載倉庫,各自的具體用法可以參考官方文檔。
命令行交互
命令行交互功能可以在用戶執(zhí)行 init 命令后,向用戶提出問題,接收用戶的輸入并作出相應(yīng)的處理。這里使用 inquirer.js 來實(shí)現(xiàn)。
const inquirer = require('inquirer'); inquirer.prompt([ { name: 'description', message: 'Input the object description' }, { name: 'author', message: 'Input the object author' } ]).then((answers) => { console.log(answers.author); })
通過這里例子可以看出,問題就放在 prompt() 中,問題的類型為 input 就是輸入類型,name 就是作為答案對(duì)象中的 key,message 就是問題了,用戶輸入的答案就在 answers 中,使用起來就是這么簡單。更多的參數(shù)設(shè)置可以參考官方文檔。
通過命令行交互,獲得用戶的輸入,從而可以把答案渲染到模板中。
渲染模板
這里用 handlebars 的語法對(duì)模板中的 package.json 文件做一些修改
{ "name": "{{name}}", "version": "1.0.0", "description": "{{description}}", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "{{author}}", "license": "ISC" }
并在下載模板完成之后將用戶輸入的答案渲染到 package.json 中
視覺美化
在用戶輸入答案之后,開始下載模板,這時(shí)候使用 ora 來提示用戶正在下載中。
const ora = require('ora'); // 開始下載 const spinner = ora('正在下載模板...'); spinner.start(); // 下載失敗調(diào)用 spinner.fail(); // 下載成功調(diào)用 spinner.succeed();
然后通過 chalk 來為打印信息加上樣式,比如成功信息為綠色,失敗信息為紅色,這樣子會(huì)讓用戶更加容易分辨,同時(shí)也讓終端的顯示更加的好看。
const chalk = require('chalk'); console.log(chalk.green('項(xiàng)目創(chuàng)建成功')); console.log(chalk.red('項(xiàng)目創(chuàng)建失敗'));
除了給打印信息加上顏色之外,還可以使用 log-symbols 在信息前面加上 √ 或 × 等的圖標(biāo)
const chalk = require('chalk'); const symbols = require('log-symbols'); console.log(symbols.success, chalk.green('項(xiàng)目創(chuàng)建成功')); console.log(symbols.error, chalk.red('項(xiàng)目創(chuàng)建失敗'));
完整示例
// index.js #!/usr/bin/env node // 處理用戶輸入的命令 const program = require('commander'); // 下載模板 const download = require('download-git-repo'); // 問題交互 const inquirer = require('inquirer'); // node 文件模塊 const fs = require('fs'); // 填充信息至文件 const handlebars = require('handlebars'); // 動(dòng)畫效果 const ora = require('ora'); // 字體加顏色 const chalk = require('chalk'); // 顯示提示圖標(biāo) const symbols = require('log-symbols'); // 命令行操作 var shell = require("shelljs"); program.version('1.0.1', '-v, --version') .command('init <name>') .action((name) => { if (!fs.existsSync(name)) { inquirer.prompt([ { name: 'description', message: 'Input the object description' }, { name: 'author', message: 'Input the object author' } ]).then((answers) => { const spinner = ora('Downloading...'); spinner.start(); download('zxpsuper/suporka-parcel-vue', name, (err) => { if (err) { spinner.fail(); console.log(symbols.error, chalk.red(err)); } else { spinner.succeed(); const fileName = `${name}/package.json`; const meta = { name, description: answers.description, author: answers.author } 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('The vue object has downloaded successfully!')); inquirer.prompt([ { type: 'confirm', name: 'ifInstall', message: 'Are you want to install dependence now?', default: true } ]).then((answers) => { if (answers.ifInstall) { inquirer.prompt([ { type: 'list', name: 'installWay', message: 'Choose the tool to install', choices: [ 'npm', 'cnpm' ] } ]).then(ans => { if (ans.installWay === 'npm') { let spinner = ora('Installing...'); spinner.start(); // 命令行操作安裝依賴 shell.exec("cd " + name + " && npm i", function (err, stdout, stderr) { if (err) { spinner.fail(); console.log(symbols.error, chalk.red(err)); } else { spinner.succeed(); console.log(symbols.success, chalk.green('The object has installed dependence successfully!')); } }); } else { let spinner = ora('Installing...'); spinner.start(); shell.exec("cd " + name + " && cnpm i", function (err, stdout, stderr) { if (err) { spinner.fail(); console.log(symbols.error, chalk.red(err)); } else { spinner.succeed(); console.log(symbols.success, chalk.green('The object has installed dependence successfully!')); } }) } }) } else { console.log(symbols.success, chalk.green('You should install the dependence by yourself!')); } }) } }) }) } else { // 錯(cuò)誤提示項(xiàng)目已存在,避免覆蓋原有項(xiàng)目 console.log(symbols.error, chalk.red('The object has exist')); } }); program.parse(process.argv);
npm publish發(fā)布你的項(xiàng)目即可。
本地測試node index init parcel-vue
以上是“如何開發(fā)一個(gè)Parcel-vue腳手架工具”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。