vue实现简易脚手架
二:配置
三:配置
3.1:配置
3.2:配置
3.3:配置
四:配置
4.1 配置
5.3 测试通过,脚手架发布到
前言:
为什么需要自己的脚手架
- 公司内部后台管理项目架构基本一样,每次新建项目都要拷贝重命名
- 没有权限或者不知道框架的存在
- 通过简单命令一键下载,快速帮助我们搭建预定义好的项目模板
实现过程:
一:脚手架组织结构
二:配置package.json
文件
配置完成后,执行npm install命令【不建议修改dependencies版本】
{
"name": "ifweb",
"version": "0.0.1",
"description": "后台管理系统脚手架",
"bin": {
"ifweb": "./bin/cli.js"
},
"scripts": {
"watch": "npm run compile -- --watch"
},
"keywords": [
"fweb-cli",
"fweb",
"后台管理",
"管理系统",
"脚手架"
],
"license": "MIT",
"dependencies": {
"axios": "^0.21.1",
"chalk": "^4.1.2",
"commander": "^8.1.0",
"download-git-repo": "^3.0.2",
"figlet": "^1.5.2",
"fs-extra": "^10.0.0",
"inquirer": "^8.1.2",
"ora": "^5.4.0"
}
}
三:配置command
目录
3.1:配置http.js
文件内容
const axios = require('axios')
axios.interceptors.response.use((res) => {
return res.data
})
/**
* 获取模版列表
* @return Promise
*/
async function getRepoList() {
return axios.get('https://api.github.com/orgs/xxx/xxx/repos')
}
/**
* 获取版本信息
* @param {string} repo 模版名称
*
*/
async function getTagList(repo) {
return axios.get(
`https://api.github.com/repos/xxx/xxx/${repo}/tags`
)
}
module.exports = {
getRepoList,
getTagList
}
3.2:配置generator.js
文件内容
const { getRepoList, getTagList } = require('./http')
const ora = require('ora')
const inquirer = require('inquirer')
const util = require('util')
const path = require('path')
const downloadGit = require('download-git-repo')
const chalk = require('chalk')
/**
* 添加动画
* @param {*} fn
* @param {*} message
* @param {...any} args
* @returns
*/
const drawLoading = async (fn, message, ...args) => {
// 使用 ora 初始化,传入提示信息 message
const spinner = ora(message)
// 开始加载动画
spinner.start()
try {
// 执行传入方法 fn
const result = await fn(...args)
// 状态修改为成功
spinner.succeed()
return result
} catch (error) {
// 状态修为失败
spinner.fail('Request fail, refetch ....', error)
}
}
class Generator {
constructor(name, targetDir) {
// 目录名称
this.name = name
// // 创建位置
this.targetDir = targetDir
// 对 download-git-repo 进行 promise 化改造
this.downloadGit = util.promisify(downloadGit)
}
/**
* 获取用户选择的模板
* @returns 用户选择的模板名称
*/
async getRepo() {
const repoList = await drawLoading(getRepoList, 'wait fetch template')
if (!repoList) return
const repos = repoList.map((item) => item.name)
const { repo } = await inquirer.prompt({
name: 'repo',
type: 'list',
choices: repos,
message: 'Please choose a template to create project'
})
return repo
}
/**
* 获取用户选择的版本
* @param {*} repo 已选择模板
* @returns 选择的 tag
*/
async getTag(repo) {
// 基于 repo 结果,远程拉取对应的 tag 列表
const tags = await drawLoading(getTagList, 'waiting fetch tag', repo)
if (!tags) return
// 过滤需要的 tag 名称
const tagsList = tags.map((item) => item.name)
// 用户选择自己需要下载的 tag
const { tag } = await inquirer.prompt({
name: 'tag',
type: 'list',
choices: tagsList,
message: 'Place choose a tag to create project'
})
return tag
}
/**
* 下载远程模板tag
*/
async download(repo, tag) {
// 下载地址
const requestUrl = `xxx/${repo}${tag ? '#' + tag : ''}`
// 调用下载方法
await drawLoading(
this.downloadGit,
'waiting download template',
requestUrl,
path.resolve(process.cwd(), this.targetDir)
)
}
/**
* 核心创建逻辑
*/
async create() {
const repo = await this.getRepo()
const tag = await this.getTag(repo)
// 下载模板到模板目录
await this.download(repo, tag)
// 模板使用提示
console.log(`\r\nSuccessfully created project ${chalk.cyan(this.name)}`)
console.log(`\r\n cd ${chalk.cyan(this.name)}`)
console.log(' npm run dev\r\n')
}
}
module.exports = Generator
3.3:配置init.js
文件内容
const path = require('path')
const fs = require('fs-extra')
const inquirer = require('inquirer')
const Generator = require('./generator')
module.exports = async function (name, options) {
// 当前命令行选择的目录
const cwd = process.cwd()
// 需要创建的目录地址
const targetAir = path.join(cwd, name)
// 目录是否已经存在
if (fs.existsSync(targetAir)) {
if (options.force) {
await fs.remove(targetAir)
} else {
// 询问用户是否确定要覆盖
let { action } = await inquirer.prompt([
{
name: 'action',
type: 'list',
message: 'Target directory already exists Pick an actions:',
choices: [
{
name: 'Overwrite',
value: 'overwrite'
},
{
name: 'Cancel',
value: false
}
]
}
])
if (!action) {
return
} else if (action === 'overwrite') {
//移除已经存在的目录
console.log(`\r\nRemoving`)
await fs.remove(targetAir)
}
}
}
const generator = new Generator(name, targetAir)
generator.create()
}
四:配置bin
目录
4.1 配置cli.js
文件内容
#! /usr/bin/env node
const commander = require('commander')
const chalk = require('chalk')
var figlet = require('figlet')
commander
.command('create <app-name>')
.description('create a new project')
.option('-f, --force', 'overwrite target directory if it exit')
.action((name, options) => {
console.log('name:', name, 'option:', options)
require('../command/init.js')(name, options)
})
.version(`v${require('../package.json').version}`)
.usage('<command> [option]')
// 配置 config 命令
commander
.command('config [value]')
.description('inspect and modify the config')
.option('-g, --get <path>', 'get value from option')
.option('-s, --set <path> <value>')
.option('-d, --delete <path>', 'delete option from config')
.action((value, options) => {
console.log(value, options)
})
commander.on('--help', () => {
// 使用 figlet 绘制 Logo
console.log(
'\r\n' +
figlet.textSync('FWEB', {
font: 'Ghost',
horizontalLayout: 'default',
verticalLayout: 'default',
width: 80,
whitespaceBreak: true
})
)
// 新增说明信息
console.log(
`\r\nRun ${chalk.cyan(`ifweb <command> --help`)} show details\r\n`
)
})
commander.parse(process.argv)
五:执行命令
5.1 本地调试
打开项目终端,执行npm link
链接到全局
5.2 全局安装脚手架
// 打开终端执行:
npm install -g ifweb
// 根据自身情况,选择磁盘执行:
cd code
ifweb create <project-name>
5.3 测试通过,脚手架发布到npm
注册npm账号:www.npmjs.com
npm镜像恢复为原始路径:npm config set registry registry.npmjs.org/
打开项目终端,执行:
// 添加npm用户
npm adduser
// 发布到npm
npm publish
六:获取模板信息
6.1 代码已上传至github/gitlab仓库
6.2 github:仓库获取地址
api.github.com/orgs/xxx/xxx/repos
6.3 github:仓库版本获取地址
api.github.com/repos/xxx/xxx
代办报建
本公司承接江浙沪报建代办施工许可证。
联系人:张经理,18321657689(微信同号)。
18条评论
看了这么多帖子,第一次看到这么有深度了!http://www.a5km.com/yxgl/dnf/23681.html
楼主很有艺术范!http://www.indaseg.com/a/a/4623.html
读了楼主的帖子,顿时马桶就通了。。。http://gufh.ppe95.net
宇宙第一贴诞生了!http://emn.freedom-visa.com
刚分手,心情不好!http://ftk.xinxiad.cn
写得实在太好了,我唯一能做的就是默默顶贴!http://pcrqb.taoxiaochong.com
楼主加油,看好你哦!http://6yu.shedesy.net
好无聊啊!http://4ts17.xgdjy.com
缺乏激情了!http://44ie2.xsjob.net
楼主写的很经典!http://j3a.bjerba.com
楼主看起来很有学问!http://jif2.jsjt888.com
楼主今年多大了?http://www.guangcexing.net/voddetail/FJxkEKchFEnby.html
今天上网不回帖,回帖就回精华帖!http://www.guangcexing.net/dvd/EZnYhCA.html
最近回了很多帖子,都没人理我!https://www.clashis.com/
世界末日我都挺过去了,看到楼主我才知道为什么上帝留我到现在!https://www.skypeis.com/
灌水不是我的目的!http://7x3.juansinigual.com
勤奋灌水,天天向上!http://e1z7.ce0fhw.cn
楼主是一个典型的文艺青年啊!https://www.btoko.com/
发表评论