我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!
大家好,我是小杜杜,继上篇讲的 10分钟,打造一个专属于你的cli ,我们已经完成了项目的下载,安装和运行。(新来的小伙伴可以先快看看(● ̄(エ) ̄●))
我们在项目开发中会遇到这样一种情况,就是在开发一些页面的时候会有相同模块,像这样
如引入的文件,固定的标签,组件等重复性的东西,除了复制粘贴,还有什么方法可以几秒就能实现呢?这时候我们可以使用cli,让他来帮助我们更快的实现
最终效果
我们先来看看最终的效果:
简单的说就是通过交互,自动实现文件的创建和路由的配置这两个功能
小技巧
可以在本地使用 npm link
在本地上直接使用即可,不用发包~
项目
在这里使用我个人的 Ant-Design-Pro-V5 ,以此来讲解(不同的项目,要进行不同的配置哦~)
创建文件
我们先来想想创建文件需要做哪些步骤,首先我们需要定义这样一个模板,让其快速构建,然后将模板复制到自己的项目即可。
所以我们这里先建立一个文件,如:
然后我们在通过遍历这个文件夹,用copyFile
将文件复制出去
const fileModule = resolve(__dirname, '../../module')
const files = fs.readdirSync(fileModule).filter((v) => ![".git"].includes(v));
// 遍历所需要的文件,执行复制
files.map(async (item) => {
const fromFileName = resolve(__dirname, `../../module/${item}`);
const toFileName = resolve(__dirname, `${desc}/${item}`);
fs.copyFile(fromFileName, toFileName, 0, () => {})
})
在这里我们可以优化一下,我们可以判断一下创建的这个文件有没有创建,如果有,可以弹个框,告诉你,这个文件已经创建过了,是否要删除后重新引入,所以我们接下来讲解下如何删除文件
要删除文件,需要删除文件内的所有子文件,在删除目录文件,要使用 fs.unlinkSync
和fs.rmdirSync
这两个方法,再配合一些提示便可实现
// desc:文件目录
const files = fs.readdirSync(desc)
files.map((item) => {
fs.unlinkSync(`${desc}/${item}`)
})
fs.rmdirSync(desc)
详细代码
create.ts:
const inquirer = require("inquirer");
const { resolve } = require("path");
const fs = require("fs") ;
const { log } = require("../api");
const filePath = 'src/pages'
module.exports = async () => {
console.log("path", resolve("."));
create()
};
async function create(){
// 项⽬名称
const name = await inquirer.prompt([{
type: 'input',
message: '设置文件名😎😎😎',
name: 'name',
}])
const desc = resolve(`./${filePath}/${name.name}`);
log(desc)
// 判断是否存在该文件,若存在则不提示
const isFile = fs.existsSync(desc)
if(isFile){
deleteFile(desc)
return
}else{
await require(`./routes`)(name.name);
createFile(desc)
return
}
}
async function createFile(desc){
try{
// 新建文件夹
fs.mkdirSync(desc)
const fileModule = resolve(__dirname, '../../module')
const files = fs.readdirSync(fileModule).filter((v) => ![".git"].includes(v));
// 遍历所需要的文件,执行复制
files.map(async (item) => {
const fromFileName = resolve(__dirname, `../../module/${item}`);
const toFileName = resolve(__dirname, `${desc}/${item}`);
fs.copyFile(fromFileName, toFileName, 0, () => {})
})
} catch {
log('创建失败', 'red')
}
}
async function deleteFile(desc){
log(desc)
try{
// 是否选择删除后重新建立
const answer = await inquirer.prompt([{
type: 'confirm',
name: 'confirm',
message: '当前文件已有此文件,是否选择删除后重新建立?',
default: false
}])
console.log("answer", answer);
if(answer.confirm){
// 删除模块,需要先删除文件,在删除目录
const files = fs.readdirSync(desc)
files.map((item) => {
fs.unlinkSync(`${desc}/${item}`)
})
fs.rmdirSync(desc)
await require(`./routes`)(answer.name);
createFile(desc)
}else{
create()
}
} catch {
log('发生错误', 'red')
}
}
创建路由
我们先来看看在V5
中的路由:
我们可以看到,文件的大概结构就是这样,其实不难发现,我们并不好去动这个路由,所以我们可以单独创建一个路由模块,之后在手动的去添加到项目中
效果:
我们以脚手架创建的文件为routesChildren.ts
在这里我们需要注意两个点
- 没有
routesChildren.ts
我们直接添加即可 - 有
routesChildren.ts
这个文件的时候我们需要读取其文件,在进行拼接
注:fs.readFile 和 fs.writeFile 要求的都是字符串,所以这里我将export default截取了下
当我们创建完之后,需要手动的把 routesChildren.ts
引入到routes
中
async function create(nameFile){
const desc = resolve(`./${filePath}`);
const isFile = fs.existsSync(desc)
const toFileName = resolve(__dirname, desc);
// 写
const start = `export default`
if(isFile){
fs.readFile(toFileName, 'utf8', async (err, data) => {
try{
const arr = JSON.parse(data.substring(14, data.length).trim())
const routerArr = await routerConfig(nameFile)
const res = [...arr, ...routerArr]
fs.writeFile(toFileName, `${start} ${JSON.stringify(res)}`, (err) => {
log('🚗🚗🚗路由创建成功')
})
}catch{
log('文本格式不对,请查看格式')
}
})
}else{
const routerArr = await routerConfig(nameFile)
// 如果没有
fs.writeFile(toFileName, `${start} ${JSON.stringify(routerArr)}`, (err) => {
log('🚗🚗🚗路由创建成功')
})
}
}
详细代码
const inquirer = require("inquirer");
const { resolve } = require("path");
const fs = require("fs") ;
const { log } = require("../api");
const filePath = 'config/routesChildren.ts'
module.exports = async (name) => {
console.log("path", resolve("."));
create(name)
};
async function create(nameFile){
const desc = resolve(`./${filePath}`);
const isFile = fs.existsSync(desc)
const toFileName = resolve(__dirname, desc);
// 写
const start = `export default`
if(isFile){
fs.readFile(toFileName, 'utf8', async (err, data) => {
try{
const arr = JSON.parse(data.substring(14, data.length).trim())
const routerArr = await routerConfig(nameFile)
const res = [...arr, ...routerArr]
fs.writeFile(toFileName, `${start} ${JSON.stringify(res)}`, (err) => {
log('🚗🚗🚗路由创建成功')
})
}catch{
log('文本格式不对,请查看格式')
}
})
}else{
const routerArr = await routerConfig(nameFile)
// 如果没有
fs.writeFile(toFileName, `${start} ${JSON.stringify(routerArr)}`, (err) => {
log('🚗🚗🚗路由创建成功')
})
}
}
async function routerConfig(nameFile){
const name = await inquirer.prompt([{
type: 'input',
message: '请设置路由名称',
name: 'name',
}])
console.log("answer", name.name);
const icon = await inquirer.prompt([{
type: 'input',
message: '请设置icon名称',
name: 'name',
default: 'FireOutlined'
}])
console.log("answer", icon.name);
return [
{
path: `/${nameFile}`,
name: name.name,
icon: icon.name,
component: `./${nameFile}`,
}
]
}
实现效果
讨论
本章中主要讲解了下如何使用 cli
创建页面,当然这个功能并不只是创建页面,也可以弄一些在项目中常用的模板,这样可能通过几秒一个模板就创建出来,是不是非常快速的一个方法?
欢迎大家留言讨论,另外附上代码地址,供大家参观,如果有帮助,给个小小的Star,支持下~~
git 地址: domesy-cli
其他好文: