两种目录结构,一个为H5多页面 , 一个为单页面项目(后台系统)
npm: npm i -g mch-vue-cli(安装命令) 使用
目录结构:
(后台系统) (H5)
目的:
因为调用接口是通过vuex来调用的 而每次一个模块需要去新建一次 很麻烦,希望一个命令自动生成 所以想到用vue脚手架的形式去生成页面模块或者接口案例
简单介绍项目:
H5是想到是用多个html形式,以多页面的形式打包 (由于公司会有很多小的H5页面,自己又不想重新去搭建一个架子,怪麻烦的,所以自己想以多个html形式搭建,就不会存在这样的问题了),两个项目都是以ts为基础,这里展示一下接口的调用:
自己项目的脚手架cli代码:
啰里啰唆了半天,该说说怎么去实现自己的想法, 查了很多的资料后,了解cli的大致流程就是:
1.通过inquire去引导
2.通过用户的选择,实现不同的功能
3.选择指定的代码仓库克隆到本地(通过download-git-repo)
4.对从git上拉下来的文件进行读写文件操作,对想要修改的内容进行修改保存(包括重命名等)
记录一下会用到的依赖:
1.fs-文件读写 2.ora-加载等待 3.path-路径 4.readline-文件按行读取 5.download-git-repo-文件下载 6.commander-定义指令 7.inquirer-交互式命令行 8.chalk-修改控制台字符串的样式
cli的目录结构:
代码:
my-vue-cli:
#!/usr/bin/env node
const program = require('commander')
// 定义当前版本
// 定义使用方法
// 定义四个指令
program
.version(require('../package').version)
.usage('<command> [options]')
.command('add', 'add a new template')
.command('delete', 'delete a template')
.command('init', 'generate a new project from a template')
// 解析命令行参数
program.parse(process.argv)
my-vue-cli-add:
#!/usr/bin/env node
// 生成模板
const { grv, grp } = require('../util/generate')
// 生成页面
const { single , multiple } = require('../util/gtdpage')
// 添加对话
const { addQA,cons } = require('../util/constants')
// 交互式命令行
const inquirer = require('inquirer')
// 修改控制台字符串的样式
const chalk = require('chalk')
// node 内置文件模块
const fs = require('fs')
inquirer.prompt(addQA)
.then(answers => {
for(let item of answers.type){
const judStore = item == cons.addStore
const judPages = item == cons.addPages
const singPage = answers.addType == cons.singlePage
const multiPage = answers.addType == cons.multiPage
if (judStore) {
singPage ? grp(answers) : grv(answers)
} else if (judPages) {
singPage ? single(answers) : multiple(answers)
}
}
})
generate.js:
// 用于改变文件内容
const fs = require('fs')
const os = require('os')
const ora = require('ora')
const path = require('path')
const readline = require('readline')
const colors = require('colors-console')
const download = require('download-git-repo')
const { cons } = require('../util/constants')
// 工具依赖
const {
removalRepeat,
downloads,
spliceFiles,
write,
read,
error,
} = require('./index')
// 常量全局
const dirname = path.join(path.resolve('./'))
const grv = (answer) => {
generate(answer)
}
const grp = (answer) => {
generate(answer)
}
const moduleCreate = (storePath, answer) => {
return new Promise(async resolve => {
let files = []
const crindex = await downloads(cons.actionRepo, storePath)
if (crindex) {
const currStoreIndex = path.join(storePath, 'index.ts')
const indexData = read(currStoreIndex)
indexData.on('line', line => {
files.push(line.replace(/\example/g, answer.name))
})
indexData.on('close', () => {
write(files,currStoreIndex)
resolve(true)
})
}
})
}
const generate = async answer => {
/**
* @variable files 数据集合
* @variable findModules modules 当前位置
* @variable findVueUse vue.use 当前位置
* @variable curr 当前读取位置
* @variable usedModules 已有模块
* @variable openIden 开启记录重复标识
*/
let files = [] , findModules = -1 , findVueUse = -1,
curr = 0, usedModules = [], openIden = false
const dirStore = path.join(dirname , 'src/store')
const storeIndex = path.join(dirStore, 'index.ts')
const indexData = read(storeIndex)
indexData.on('line', line => {
const brace = line.includes(cons.closeBrace)
const modules = line.includes(cons.modules)
const colon = line.includes(cons.colon)
const use = line.includes(cons.use)
files.push(line)
if(use) findVueUse = curr
if(modules && colon)(findModules = curr, openIden = true)
/**
* @judgement curr > findModules 当前读取的位置大于标记modules的位置时开始判断
* @judgement findModules != -1 标记不为初始值时
* @judgement openIden 标记是否打开过
*/
if (curr > findModules && findModules != -1 && openIden) {
if(!brace && line != '') usedModules.push(line.trim())
else openIden = false
}
curr ++
})
indexData.on('close' , async () => {
const isRepeat = removalRepeat(usedModules , answer.name)
const storePath = path.join(path.resolve('./src/store'), answer.name)
spliceFiles(files, answer , {findModules,findVueUse})
if(!isRepeat){
const currtModule = await moduleCreate(storePath, answer)
currtModule ? write(files, storeIndex) : null
}else error('--------当前模块已重复--------')
})
}
module.exports = {
grv,
grp
}
constants.js:
const initQA = [{
type: 'input',
message: "请输入当前模板名字:",
name: "file",
default: "example"
},{
type: "confirm",
message: "是否需要初始化默认调用接口方式:",
name: "api",
default: true
}]
const addQA = [{
type: 'checkbox',
message: '请选择项目类型:',
name: 'type',
choices: [
"添加store",
"添加页面"
],
default: ['添加store'],
validate: data => {
if(data != '') return true;
return "请选择添加类型";
}
},{
type: 'list',
message: '请选择添加类型:',
name: 'addType',
choices: [
"多页面",
"单页面"
]
},{
type: 'input',
message: "请输入需要添加模块的名字:",
name: "name",
default: "example"
}]