在實際的開發過程當中,從零開始創建項目的結構是一件讓人頭疼的事情,因此各類各樣的腳手架工具應運而生。它們功能豐富,但最核心的功能都是可以快速搭建一個完整的項目的結構,開發者只須要在生成的項目結構的基礎上進行開發便可,很是簡單高效。vue
接下來就讓咱們一來看看一個腳手架是如何從0開始搭建的吧。node
總體架構以下圖: webpack
一個模板就是一個項目的樣板,包含項目的完整結構和信息。 咱們把模板信息都存放在一個文件中scaffold-config-dev.json
。 用戶經過選擇不一樣模板,經過 axios 下載遠程倉庫模板到本地,完成項目的搭建ios
最終整個腳手架的文件結構以下:git
=================
├── bin
│ └── ivue-material-cli.js
├── node_modules
├── package.json
└── packages
└── src
├── commander
│ └── index.js
├── lib
│ └── utils
│ └── log.js
└── locals
├── index.js
└── zh_CN
└── index.js
複製代碼
包名稱 | 功能 |
---|---|
commander | 可以更好地組織和處理命令行的輸入 |
chalk | 輸出有顏色的命令行 |
mz | 在node中使用 es6 |
咱們先從最簡單的步驟開始,-v 輸出版本號。es6
首先咱們須要知道,-v後命令須要輸出什麼內容,因此咱們在locals
目錄對輸出的內容進行國際化內容的管理,在這裏咱們一切從簡,使用中文內容。github
zh_CN->index.jsweb
module.exports = {
LANG: 'zh_CN',
SHOW_VERSION: '查看當前版本',
NO_COMMAND: '命令不存在'
};
複製代碼
而後在locals
文件下對內容文件進行管理。vue-cli
locals->index.jsjson
module.exports = function () {
let lang = process.env.LANG || 'zh_CN';
if (/zh/g.test(lang)) {
return require('./zh_CN');
}
};
複製代碼
咱們知道一個好看的命令好必需要有顏色,接下來咱們須要使用chalk
來對命令行進行上色。咱們在 lib->utils
文件夾下對其進行管理。
/**
* @file logger
*/
'use strict';
/* eslint-disable */
const chalk = require('chalk');
const util = require('util');
let log = {};
// 管理命令 log 顏色
let logTypes = [
{
name: 'info',
color: chalk.green,
level: 2
},
{
name: 'error',
color: chalk.red,
level: 4
}
];
logTypes.forEach(function (item) {
/**
* 定義打印日誌格式
*
* @param {string} format 要輸出的內容.
* @param {...*} varArgs 變長參數.
*/
log[item.name] = function (format, varArgs) {
// 格式化輸出字符串
let msg = util.format.apply(null, arguments);
if (msg) {
console.log((log.prefix || 'IVUE') + ' ' + item.color(item.name.toUpperCase()) + ' ' + msg);
}
else {
console.log();
}
};
});
module.exports = log;
複製代碼
接下來咱們來編寫 -v 命令,咱們在 commander
文件夾下對命令行進行管理,咱們使用 ```commander`` 插件輸出命令行由於其可以更好地組織和處理命令行的輸入
index.js
// 可以更好地組織和處理命令行的輸入
const program = require('commander');
// 內容文件
const locals = require('../locals')();
// 命令行顏色
const log = require('../lib/utils/log');
// 版本號
let version = process.env.VERSION || require('../../../package.json').version;
// 獲取輸入的命令行
let argv = process.argv[2];
if (argv === '-v' || argv === '--version') {
log.info('ivue version: ', version);
}
// 定義命令
program
// 設置/獲取命令用法str
.usage('[commands] [options]')
// 定義頂級命令的參數語法。
.arguments('<cmd> [env]')
// 當使用 --help 時,all 將以這種方式輸出。
// 查看當前版本
.option('-v, --version', locals.SHOW_VERSION)
// 註冊命令的回調
.action((cmd, env) => {
// 輸出錯誤
if (env) {
log.error(`\`ivue ${cmd} ${env}\` ${locals.NO_COMMAND}`);
}
else {
log.error('`ivue ' + cmd + '` ' + locals.NO_COMMAND);
}
});
// 處理參數
program.parse(process.argv);
複製代碼
執行 -v 後輸出以下:
接下來咱們來繼續構建 -h 幫助命令,修改 commander->index.js
文件
····
// 在node 中使用 es6 語法
const exec = require('mz/child_process').exec;
// 若是後序沒有輸入命令,執行幫助指令
if (!process.argv[2]) {
let output = exec('ivue -h');
console.log(output[0]);
}
// 獲取版本號
else {
let argv = process.argv[2];
if (argv === '-v' || argv === '--version') {
log.info('ivue version: ', version);
}
}
····
複製代碼
最終輸出以下:
以上也正是 ivue-cli
腳手架的一部分的源碼。
下一篇咱們將繼續講解最複雜的功能 init 命令
本文章將一直持續更新到腳手架所有源碼的講解~~~~
若有不對歡迎提出您寶貴的意見
歡迎各位提出 issues
或者 star
。
github倉庫地址: