原因
在工作中,需要開發一個腳手架,用於給相關使用者提供相關的開發便利性。
適合人群
對前端、Node 操作有一定的瞭解,同時想了解腳手架開發過程或者需要自己實現一個腳手架的開發者。
目標
- 開發一個簡單的腳手架,能夠提供給使用者進行安裝。
- 能夠輸出相關提示。
- 對使用者檔案進行讀寫操作。
- 在腳手架中使用 Shell 指令碼。
步驟
開發腳手架
腳手架的開發最開始過程與普通的前端專案相同,需要一個入口檔案 command.js
和配置檔案 package.json
。
與其他配置檔案不同的是,你需要在 command.js
檔案第一行增加如下宣告:
#! /usr/bin/env node
複製程式碼
同時需要在 package.json
檔案中加上一下一項:
{
...,
"bin": {
"cm-cli": "command.js"
}
}
複製程式碼
在配置檔案中增加了此項後,只需要在配置檔案根目錄下執行 npm link
命令,即可使用 cm-cli --help
命令來檢視載入的 cm-cli 腳手架(需要保證 command.js 能夠處理響應,詳情見下一節,放在此處是為了文章方便閱讀)。
如果你釋出了你的腳手架,那麼在其他使用者使用命令 npm install -g cm-cli
之後,便可以在全域性下使用你的腳手架了。
對使用者進行提示
在對註釋和命令進行提示中,我們需要使用到 commander
包,使用 npm install commander
即可進行安裝。(如果NPM版本低於5,則需要新增 --save
引數保證更新 package.json
配置檔案)。
commander
是一個提供使用者命令列輸入和引數解析的強大功能。有需要的可以閱讀相關的庫文件。在這裡我介紹兩個用的最多的方法。
option
能夠初始化自定義的引數物件,設定關鍵字和描述,同時還可以設定讀取使用者輸入的引數。具體用法如下:
const commander = require('commander');
commander.version('1.0.0')
.option('-a, --aaa', 'aaaaa')
.option('-b, --bbb', 'bbbbb')
.option('-c, --ccc [name]', 'ccccc')
.parse(process.argv);
if (commander.aaa) {
console.log('aaa');
}
if (commander.bbb) {
console.log('bbb');
}
if (commander.ccc) {
console.log('ccc', commander.ccc);
}
複製程式碼
此時如果已經配置完成並且執行過 npm link
命令後,可以看到如下結果:
command
該方法能夠在命令列增加一個命令。使用者在執行此命令後,能夠執行回撥中的邏輯。具體用法如下:
commander
.command('init <extensionId>')
.description('init extension project')
.action((extensionId) => {
console.log(`init Extension Project "${extensionId}"`);
// todo something you need
});
複製程式碼
具體展示效果如下:
對使用者檔案進行讀寫操作
通過上面的步驟,我們已經能夠完成一個簡單的腳手架了。下面,我們需要讀取使用者配置,同時為使用者生成一些模板檔案。
讀取檔案
現在,我們需要讀取使用者的 cm-cli.json
配置檔案來進行一些配置。
我們可以使用 Node.js 的 fs
檔案模組來對檔案進度讀操作,由於此處沒有太多難點,因此略去。
寫入檔案模板
我們提前將模板檔案儲存在 CDN 上,再根據本地讀取到的相關腳手架配置檔案來進行模板的下載。
注:腳手架中讀取的路徑為使用者使用時當前路徑,因此沒有辦法將模板檔案儲存在腳手架中進行讀取。
我們可以使用諸如 request
這種庫來幫助我們進行檔案下載,簡化操作步驟。執行 npm install request
即可進行安裝。
注:在檔案寫入時建議先判斷檔案是否存在,再進行覆蓋。
使用 Shell 指令碼
與 Node.js 提供的 API 函式來看,有些人更加傾向於使用 Shell 指令碼來進行檔案操作。幸運的是,我們也可以在我們的腳手架中引入 node-cmd
來啟用對 Shell 指令碼的支援。執行 npm install node-cmd
即可進行安裝。
具體示例如下:
commander
.command('init <extensionId>')
.description('init extension project')
.action((extensionId) => {
id = extensionId;
console.log(`init Extension Project "${extensionId}"`);
cmd.get(
`
mkdir -p static/${extensionId}
mkdir tmp
mkdir tmp/source-file
mkdir tmp/build-file
curl -o tmp/source-file/index.js https://xxxxxxxx.com?filename=index.js
touch tmp/source-file/index.css
curl -o tmp/build-file/server.js https://xxxxxxxx.com?filename=server.js
curl -o tmp/build-file/router.js https://xxxxxxxx.com?filename=router.js
curl -o tmp/build-file/package.json https://xxxxxxxx.com?filename=package.json
cp tmp/source-file/* static/${extensionId}
cp tmp/build-file/* ./
rm -fr tmp
npm install
`,
(err, data) => {
console.log(data)
if (!err) {
console.log('init success');
return;
}
console.error('init error');
});
});
複製程式碼
我們可以快速的使用 Shell 指令碼來進行資料夾的建立和檔案模板的下載。
總結
腳手架想要在終端能夠快速執行,可以在 package.json
配置檔案中增加相關欄位。
腳手架需要能夠讀取相關終端輸入,可以使用 commander
庫來快速開發。
腳手架需要能夠執行 Shell 指令碼,可以使用 node-cmd
庫來快速實現需求。