上一篇文章寫了一下joao-cli的基本思路,部分同窗反應看不懂,此次直接帶你們手寫一個本身的cli工具,能夠實現前端
步驟會給出對應gif圖,圖不動的話建議右鍵新鏈接打開.
vue
1.初始化npm並安裝對應依賴.node
// 新建一個文件夾用以存儲cli工具, 當前目錄打開命令行
npm init
package name 輸入你的cli name
能夠一路回車跳過剩下內容...
複製代碼
2.註冊node.jsgit
在當前目錄新建command.js 寫上
#! /usr/bin/env node
console.log('執行了command腳本')
// 登記以上內容, 使command.js能夠被node執行
// 而後在packge.json裏添加 "bin": { "joao": "./command.js" }
{
"name": yourcli", "version": "0.0.1", "description": "快速搭建前端整站, 工程化自動開發", "main": "command.js", "dependencies": {}, "devDependencies": {}, "bin": { "joaocli": "./command.js" } } // 當前路徑打開命令行工具 鍵入npm link, 聲明環境變量 npm link // 成功後, 鍵入joaocli 會提示腳本 joaocli ... 執行了command腳本 複製代碼
3.安裝要用到的依賴github
安裝依賴 | 安裝目的 |
---|---|
commander | 命令行工具 |
fs | 用來處理文件 |
git-clone | 用來從git託管地址下載你的文件 |
inquirer | 命令行中可使用對話或者選項了 |
path | 用來處理路徑 |
shelljs | 用來執行shell |
tracer | 用來花式打log |
安裝方法: pageage.json所在目錄, npm install ${對應的依賴名稱}
web
npm install commander
npm install fs
...
複製代碼
作好準備工做後(安裝完全部依賴!), 你已經擁有了可執行的腳本, 如今咱們要一一完善各項功能
shell
//修改command.js
#! /usr/bin/env node
console.log('執行了command腳本')
const commander = require('commander');
const inquirer = require('inquirer');
const questions = [
{
type: 'input',
name: 'projectName',
message: '請爲項目命名',
filter: function(val) {
return val;
}
},
{
type: 'list',
name: 'type',
message: '請選擇使用的模板',
choices: ['empty-vue-template', '模板2', '模板3'],
filter: function(val) {
return val.toLowerCase();
}
}
]
// 新建項目 拉取模板
commander
.command('init')
.description('用來初始化項目, 拉取模板')
.action(() => {
console.log('正在構建...')
inquirer.prompt(questions)
.then(answers => {
console.log('answers', answers)
})
})
// 此行內容落下會使命令行監聽失效
commander.parse(process.argv)
複製代碼
如今鍵入 joaocli init 會輸出對話, 並獲取用戶輸入的內容和選項npm
引入git clone, 用來進行git 引入shelljs, 用來刪除項目的.git文件 引入tracer, 用來彩色consolejson
const clone = require('git-clone');
const shell = require('shelljs');
const log = require('tracer').colorConsole();
複製代碼
添加必要常量bash
// 項目地址
const projectUrl = {
'empty-vue-template': 'https://github.com/murongqimiao/joao-template', // 空白庫
}
複製代碼
在拿到用戶輸入內容的回調後
const { projectName, type } = answers
console.log(projectName)
console.log(type)
clone(`${projectUrl[type]}`, `./${projectName}`,null, function() {
log.info('項目構建完成')
shell.rm('-rf', `./${projectName}/.git`);
log.info(`清除掉${projectName}的git, 記得進入項目npm install`)
})
複製代碼
如今在你的目錄下執行 joaocli init
吧! 你將拉下一個模板項目並清除.git
const path = require('path')
複製代碼
在packgejson的同級目錄下添加物料文件夾
mkdir material
cd material
複製代碼
添加新的commander實現物料下載
// 更新物料
commander
.command('update')
.description('更新物料庫')
.action(() => {
let pwd = shell.pwd()
shell.cd(__dirname)
shell.exec('rm -rf .git')
const updateFiles = () => {
shell.cd(path.join(__dirname, '/material'))
shell.rm('-rf', '*')
shell.cd(__dirname)
shell.exec('git pull origin master')
}
shell.exec('git init')
shell.exec('git remote add origin git@github.com:murongqimiao/joao-website.git') // 物料倉庫
shell.exec('git config core.sparseCheckout true')
shell.exec("echo 'material' >> .git/info/sparse-checkout")
updateFiles()
})
// 很是重要
commander.parse(process.argv)
複製代碼
執行joaocli update 便可更新物料到 /material 下
關於物料的管理有不少辦法, 這裏筆者採用較爲簡單的git倉庫創建專有文件夾託管物料, 利用git的 core.sparseCheckout來下載部分文件夾並非最好的辦法
,由於就git的工做機制而言, sparseCheckout依然是追蹤全部的歷史變動,再刪去沒必要要內容
,若是項目在github託管,還能夠把github的倉儲轉爲svn再下載,具體操做能夠查閱svn如何下載github的部份內容
,由於咱們廠的代碼放在gitlab上,因故採用了core.sparseCheckout來下載物料文件.
同時由於引用下載整個項目, 執行update的時候會特別慢,請耐心等待.
update成功後material文件爲下會增長組件文件夾generate_components與module文件夾generate_modules
const fs = require('fs')
複製代碼
command.js中繼續添加內容
/**
* 引入一些能夠抽離的內容: commander快捷鍵 | getComponentsFiles獲取目錄 |_getFileName 獲取是文件仍是文件夾 | generateComponent 在指定目錄放置目標文件
**/
commander.version('1.0.0')
.option('-c, --component', 'Add component')
.option('-p, --page', 'Add page')
const getComponentsFiles = () => {
return _getFileName('../material/generate_components')
}
const _getFileName = (url) => {
let _url = path.join(__dirname, url)
let _back = fs.readdirSync(_url)
return _back
}
const generateComponent = (componentType, fileName, pwd) => {
fs.readFile(path.join(__dirname, `./material/generate_components/${componentType}${fileName}`), 'utf-8', (error, data) => {
if (error) throw error
// if (componentName) {
// data = data.replace(/__className__/g, componentName)
// componentType = componentName
// }
fs.writeFile(path.join(`${pwd}/src/components/${componentType}${fileName}`), data, (err) => {
if(err) {
console.log('err:', err);
} else {
console.log(`${componentType}${fileName}寫入成功!...`)
}
})
})
}
// 添加物料
commander
.command('add [args...]')
.description('增長物料 -c 組件 -p 頁面')
.action((args) => {
// 缺乏參數
if (!commander.component && !commander.page) {
log.warn('缺乏參數-c或者-p, 以區分物料種類, 具體見--help')
}
// 增長組件
if (commander.component) {
let pwd = shell.pwd()
args.map(componentType => {
_componentType = getComponentsFiles().indexOf(componentType) > -1 ? componentType : getComponentsFiles().indexOf(componentType + '.vue') > -1 ? componentType + '.vue' : void 0
if (!_componentType) {
log.warn(`:${componentType} --> 組件不存在, 請檢查拼寫`)
} else {
let _filePath = path.join(__dirname, `./material/generate_components/${_componentType}`)
let _isFile = fs.statSync(_filePath).isFile()
if (_isFile) {
generateComponent(_componentType, '', pwd)
} else {
let _aimFiles = fs.readdirSync(_filePath)
// 建文件夾
fs.mkdir(`${pwd}/src/components/${_componentType}`, 0777, (err) => {
if (err) {
log.info(`${componentType}目錄已經創建`)
}
})
_aimFiles.map(item => {
generateComponent(_componentType, `/${item}`, pwd)
})
}
}
})
}
// 增長頁面
if (commander.page) {
/**
* 這裏是添加modules的邏輯,接下來補充
**/
}
})
...上面的內容一樣添加到這句話前面
// 很是重要
commander.parse(process.argv)
複製代碼
如今在你init出來的空項目中, 根目錄執行 joaocli add -c empty 或者 joaocli add -c Layout 來測試可否正常添加物料吧!
能添加components後, 添加modules就沒有那麼困難了, 和組件相比只是多了一個自定義路徑
首先添加新的問題
const modulesFileContent = ['data.js', 'index.js', 'vx.js', '__className__.vue']
// 引入page構建問題
const pageQuestions = [
{
type: 'input',
name: 'modelType',
message: '請輸入想要使用的頁面種類',
filter: function(val) {
return val;
}
}
]
複製代碼
添加增長moduls的邏輯
/**
* 在目標文件中增長對應的page(單個添加)
*/
const generateModule = (modelType, pageName, fileName, pwd) => {
let aimFileName = fileName
let _directory = ''
// 考慮一級目錄
if (pageName.split('/').length > 2) {
console.log('目前最多支持2級目錄,好比dashboard/example')
}
if (pageName.split('/').length === 2) {
_directory = pageName.split('/')[0] + '/'
pageName = pageName.split('/')[1]
}
if (new RegExp(/.vue/).test(fileName)) {
aimFileName = pageName + '.vue'
}
fs.readFile(path.join(__dirname, `./material/generate_modules/${modelType}/${fileName}`), 'utf-8', (error, data) => {
if (error) throw error
data = data.replace(/__className__/g, pageName)
fs.writeFile(path.join(`${pwd}/src/views/${_directory}${pageName}/${aimFileName}`), data, (err) => {
if(err) {
console.log('err:', err);
} else {
console.log(`${fileName}寫入成功!...`)
}
})
})
}
// 增長頁面
if (commander.page) {
/**
* 這裏是添加modules的邏輯補充
**/
inquirer.prompt(pageQuestions)
.then(answers => {
const { modelType } = answers
let pwd = shell.pwd()
console.log(`commander.page`, args)
args.map(pageName => {
console.log('pageName', pageName)
// 建立對應目錄的文件夾
if (pageName.split('/').length === 2) {
fs.mkdir(`${pwd}/src/views/${pageName.split('/')[0]}`, 0755, (err) => {
log.info(`${pageName.split('/')[0]}已存在`)
})
}
fs.mkdir(`${pwd}/src/views/${pageName}`, 0755, (err) => {
log.info(`${pageName}已存在`)
})
/* 讀取./generate_modules下面的文件 */
modulesFileContent.map(fileName => {
generateModule(modelType, pageName, fileName, pwd)
})
})
})
}
複製代碼
在模板項目的根目錄執行
joaocli add -p yourlogin
複製代碼
再輸入對應module類型, 好比login
就完成了一鍵安裝modules的過程.
npm install -g joao-cli
複製代碼
進入joao-cli的目錄,直接看代碼便可, 徹底一致.
目前物料很少, 有時間會維護, 歡迎各路大佬塞物料來, 建議添加README.md , 放置物料使用方法和收款碼, 有同窗用的爽能夠打賞給物料開發者.