前端脚手架搭建(part4)动态插入

news2025/8/6 3:40:43

例如控制模板的name、选择使用的插件,动态插入

之前vue模板是有选择是否使用pinia、unocss,通过用户的选择,在项目中动态配置插件

需要用到ejs读取模板,然后动态修改

npm install ejs

在libs/utils/index.js添加ejs模板的操作函数

import fs from 'fs-extra'
import path from 'path'
import ejs from 'ejs'

const {existsSync,statSync,readdirSync,rmdirSync,unlinkSync} = fs;
/**
* 文件读写操作
* @param {string} targetDir 当期目录
* @param {string} filename  文件名
* @param {object} answer 回答
*/
export function fileControl(targetDir, filename, answer) {
    fs.readFile(path.join(targetDir, filename)).then(res => {
        const str = res.toString()
        const html = ejs.render(str, answer)
        fs.writeFile(path.join(targetDir, filename), html)
    })
}
/**
* 判断是否有同名文件夹
* @param {string} projectName  文件名
*/
export const isFileExist = (projectName) => {
    const targetDir = path.join(process.cwd(), projectName)
    return fs.existsSync(targetDir)
  }
  /*path:文件名*/
export function delPath(path) {
    if (!existsSync(path)) {
      console.log("路径不存在");
      return "路径不存在";
    }
    const info = statSync(path);
    if (info.isDirectory()) {//目录
      const data = readdirSync(path);
      if (data.length > 0) {
        for (let i = 0; i < data.length; i++) {
          delPath(`${path}/${data[i]}`); //使用递归
          if (i == data.length - 1) { //删了目录里的内容就删掉这个目录
            delPath(`${path}`);
          }
        }
      } else {
        rmdirSync(path);//删除空目录
        return true
      }
    } else if (info.isFile()) {
      unlinkSync(path);//删除文件
      return true
    }
  }

在libs/data/vue.config.json

[
    {
      "name": "pinia",
      "message": "是否使用pinia", 
      "type": "confirm",
      "default": true
    },
    {
        "name": "unocss",
        "message": "是否使用unocss", 
        "type": "confirm",
        "default": true
      }
  ]
  

在libs/data/react.config.json

[ 
{
    "name": "mobx",
    "message": "是否使用mobx", 
    "type": "confirm",
    "default": true
  },
    {
        "name": "unocss",
        "message": "是否使用unocss", 
        "type": "confirm",
        "default": true
      }
  ]
  

libs/constant.js

import fs from 'fs-extra'
import path from 'path'
import { fileURLToPath } from 'url'
const __filenameNew = fileURLToPath(import.meta.url)
const __dirnameNew = path.dirname(__filenameNew)

// 根目录
export const rootPath = __dirnameNew.slice(0, __dirnameNew.length - 4)

// 获取package.json文件内容
export const packageJsonData = JSON.parse(fs.readFileSync(rootPath + 'package.json', 'utf8'))


// 获取当前模板列表
export const questionList = JSON.parse(fs.readFileSync(rootPath + 'libs/data/demo.config.json', 'utf8'))

//vue插件配置
export const vueConfigList = JSON.parse(fs.readFileSync(rootPath + 'libs/data/vue.config.json', 'utf8'))
//react 插件配置
export const reactConfigList = JSON.parse(fs.readFileSync(rootPath + 'libs/data/react.config.json', 'utf8'))

libs/command/index.js

主要更改handleDownLoad 逻辑


import downLoad from 'download-git-repo'
import path from 'path'
import inquirer from 'inquirer'
import ora from 'ora';
import chalk from 'chalk';
import fs from 'fs-extra'
import {questionList,vueConfigList,reactConfigList} from '../constant.js';
import {isFileExist,fileControl,delPath} from '../utils/index.js'
//设置检测重名的问题交互
const folder = [
    {
        name: "folder",
        message: "当前目录已存在,请选择",
        type: "list",
        choices: [
            {
                name: "覆盖",
                value: "cover"
            },
            {
                name: "重命名",
                value: "rename"
            }
        ]
    },
    {
        name: 'newName',
        // 这里设置当前面用户选择重命名后,让用户输入新名称
        when: answer => answer.folder === 'rename',
        type: 'input',
        message: '目录名称为:'
    }

]

const handleDownLoad = (projectName) => {
    inquirer.prompt(questionList).then(res => {
        const targetDir = path.join(process.cwd(), projectName)
        // 获取到第一项中,用户选择的值,这里偷了个懒,大家可以根据答案和问题获取对应下载链接。
        const info = questionList[0].choices.find(item => item.value === res.features)
        const configAnswer = res.features === 'vue' ? vueConfigList : reactConfigList
        inquirer.prompt(configAnswer).then(result => {
          /*** 初始化loading图标文字 start */
          const spinner = ora('模版下载中 ...')
          /*** 初始化loading图标文字 end */
          spinner.start()
          downLoad(`direct:${info.link}`, targetDir, { clone: true }, (err) => {
            if (err) {
              spinner.fail()
              console.log(chalk.red(err))
              console.log(chalk.red('获取模版失败'))
            } else {
              // 获取所有的用户问题答案,并以用户create名称为项目名称
              const answer = { name: projectName, ...res, ...result }
              // 处理package.json对应交互变更
              fileControl(targetDir, 'package.json', answer)
              //处理vite.config.ts
              fileControl(targetDir, 'vite.config.ts', answer)
              //处理index.html
              fileControl(targetDir, 'index.html', answer)
              if (answer.features === 'vue') {
                // 处理入口文件相关变更main.js
                fileControl(targetDir, '/src/main.ts', answer)
                if (!answer.pinia) {
                  delPath(path.join(targetDir, '/src/store'))
                }
              } else if (answer.features === 'react') {
                fileControl(targetDir, '/src/main.tsx', answer)
                fileControl(targetDir, '/src/views/index/index.tsx', answer)
                if (!answer.mobx) {
                  delPath(path.join(targetDir, '/src/store'))
                }
              }
              const spinner = ora('获取模版成功')
              spinner.succeed()
              // console.log(chalk.green('获取模版成功'))
    
            }
            spinner.stop()
          })
        })
    
      })
}
const handleChecKName = (name) => {
    // 清空控制台
    console.clear()
    if (isFileExist(name)) {
        inquirer.prompt(folder).then(res => {
            if (res.folder === 'cover') {
                const targetDir = path.join(process.cwd(), name)
                const loadingMsg = ora(`正在删除 ${chalk.cyan(targetDir)}...`)
                loadingMsg.start()
                fs.remove(targetDir).then(val => {
                    loadingMsg.succeed()
                    loadingMsg.stop()
                    handleDownLoad(name)
                })
            } else {
                handleChecKName(res.newName)
            }
        })
    } else {
        handleDownLoad(name)
    }
}
export default handleChecKName;

执行命名npx mfex-project create mfex-react

就会把相关配置引入

不使用unocss和mobox

前端脚手架搭建结束,下面可以发到npm上

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/394230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IOS - 抓包通杀篇

IOS中大多数情况&#xff0c;开发者都会使用OC提供的api函数&#xff0c;CFNetworkCopySystemProxySettings来进行代理检测&#xff1b; CFNetworkCopySystemProxySettings 检测函数直接会检测这些ip和端口等&#xff1a; 采用直接附加页面进程&#xff1a; frida -UF -l 通…

04 | 在OAuth 2.0中,如何使用JWT结构化令牌? 笔记

04 | 在OAuth 2.0中&#xff0c;如何使用JWT结构化令牌&#xff1f; JWT 结构化令牌 JSON Web Token&#xff08;JWT&#xff09;是一个开放标准&#xff08;RFC 7519&#xff09;&#xff0c;它定义了一种紧凑的、自包含的方式&#xff0c;用于作为 JSON 对象在各方之间安全地…

28个案例问题分析---10---对生产环境的敬畏--生产环境

一&#xff1a;背景介绍 1&#xff1a;上午9:23&#xff0c;老师没有进行上课&#xff0c;但是却又很多的在线人员&#xff0c;并且在线人员的时间也不正确。 2&#xff1a;开发人员及时练习用户&#xff0c;查看用户上课情况。 3&#xff1a;10点整&#xff0c;询问项目组长发…

BFD配置实验

BFD配置实验拓扑图静态路由联动BFDOSPF联动BFD拓扑图 其中地址各自配置自己的loopback接口&#xff0c;然后接口地址按照AB.1.1.X进行配置。 静态路由联动BFD AR1&#xff1a; [Huawei]bfd [Huawei]bfd 1 bind peer-ip 12.1.1.2 source-ip 12.1.1.1 auto [Huawei]ip route-st…

【强化学习】一文读懂,on-policy和off-policy

一文读懂&#xff0c;on-policy和off-policy 我来谈一下我的理解&#xff0c;不一定对。本文以 Sarsa 和 Q-learning 为例 Sarsa:on-policyQ-learning:off-policy 1. 什么是on-policy和off-policy&#xff1f; 我们有两个策略&#xff1a;行动策略和目标策略 on-policy: 行…

【python】为你绘制玫瑰一束,爱意永存

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 若是有真情&#xff0c;爱意如溪水&#xff0c; 若是有真爱&#xff0c;爱意如阳光&#xff0c; 若是两情相悦&#xff0c;又岂在朝朝暮暮&#xff0c; 女子淡淡的情愫&#xff0c;深深地想念&#xff0c; 浓浓的爱意&a…

Linux :理解编译的四个阶段

目录一、了解编译二、认识编译的四个阶段&#xff08;一&#xff09;预处理&#xff08;二&#xff09;编译&#xff08;三&#xff09;汇编&#xff08;四&#xff09;链接1.静态链接2.动态链接三、分步编译&#xff08;一&#xff09;创建.c文件&#xff08;二&#xff09;预…

【项目】Java树形结构集合分页,java对list集合进行分页

Java树形结构集合分页需求难点实现第一步&#xff1a;查出所有树形集合数据 &#xff08;需进行缓存处理&#xff09;selectTree 方法步骤&#xff1a;TreeUtil类&#xff1a;第二步&#xff1a;分页 GoodsCategoryController分页getGoodsCategoryTree方法步骤&#xff1a;第三…

MySQL数据库基本操作-DQL

概念 数据库管理系统一个重要功能就是数据查询&#xff0c;数据查询不应只是简单返回数据库中存储的数据&#xff0c;还应该根据需要对数据进行筛选以及确定数据以什么样的格式显示。 MySQL提供了功能强大、灵活的语句来实现这些操作。 MySQL数据库使用select语句来查询数据 语…

ansible组件介绍和简单playbook测试

一、ansible inventory 在大规模的配置管理工作中&#xff0c;管理不同业务的机器&#xff0c;机器的信息都存放在ansible的inventory组件里面。在工作中&#xff0c;配置部署针对的主机必须先存放在Inventory里面&#xff0c;然后ansible才能对它进行操作。默认的Ansible的in…

docker常用命令,基于linux+centos7

启动docker systemctl start docker 重启docker systemctl restart docker docker自启动 systemctl enable docker 查看所有docker&#xff0c;包括正在运行的和关闭的 docker ps -a 查看正在运行的docker docker ps 停止正在运行的docker。通过id或者docker名称 do…

Ceph介绍

分布式存储概述 常用的存储可以分为DAS、NAS和SAN三类 DAS&#xff1a;直接连接存储&#xff0c;是指通过SCSI接口或FC接口直接连接到一台计算机上&#xff0c;常见的就是服务器的硬盘NAS&#xff1a;网络附加存储&#xff0c;是指将存储设备通过标准的网络拓扑结构&#xff…

client打包升级

目录 前言 一、client如何打包升级&#xff1f; 二、使用步骤 1.先进行改版本 2.执行打包升级命令 总结 前言 本文章主要记录一下&#xff0c;日常开发中&#xff0c;常需要进行打包升级的步骤。 一、client如何打包升级&#xff1f; # 升级发布版本 ## 修改版本 * 父p…

链表经典面试题【典中典】

&#x1f4af;&#x1f4af;&#x1f4af;链表经典面试题❗❗❗炒鸡经典&#xff0c;本篇带有图文解析&#xff0c;建议动手刷几遍。&#x1f7e5;1.反转链表&#x1f7e7;2.合并两个有序链表&#x1f7e8;3.链表分割&#x1f7e9;4.链表的回文结构&#x1f7e6;5.相交链表&…

74. ‘pip‘不是内部或外部命令,也不是可运行的程序-解决办法

74. pip’不是内部或外部命令&#xff0c;也不是可运行的程序-解决办法 文章目录74. pip不是内部或外部命令&#xff0c;也不是可运行的程序-解决办法1. 课题导入2. 手动配置环境变量1. 准备工作2. 配置步骤3. 命令行安装1. 课题导入 有的同学在使用pip安装第三方库时&#xf…

elasticsearch 分布式搜索引擎1

1.初识elasticsearch 1.1.了解ES 1.1.1.elasticsearch的作用 elasticsearch是一款非常强大的开源搜索引擎&#xff0c;具备非常多强大功能&#xff0c;可以帮助我们从海量数据中快速找到需要的内容 例如&#xff1a; 在GitHub搜索代码 在电商网站搜索商品 在百度搜索答案 在…

WorksPace一款简化修改IP繁琐重复性工作的高效工具

WorksPace简介 workspace软件中文版是一个集成修改网卡IP、网络扫描、记事本、快速启动的效率工具&#xff0c;前端使用Flutter&#xff0c;后端主要是Dart&#xff0c;少量的后台功能用以前Golang&#xff0c;数据存储使用SQLite。主要是为了简化我在日常工作中的频繁重复操作…

app里未读消息已读、未读是怎么设计的?

也不知道大家目前都用的java编程软件有哪些&#xff0c;毕竟在应用程序中&#xff0c;未读和已读消息的设计取决于应用程序的需求和目标。下面是一些常见的设计模式&#xff1a;一、简单的未读/已读标记简单的未读/已读标记&#xff1a;这是最常见的设计&#xff0c;用户打开应…

Linux - Linux系统优化思路

文章目录影响Linux性能的因素CPU内存磁盘I/O性能网络宽带操作系统相关资源系统安装优化内核参数优化文件系统优化应用程序软件资源系统性能分析工具vmstat命令iostat命令sar命令系统性能分析标准小结影响Linux性能的因素 CPU CPU是操作系统稳定运行的根本&#xff0c;CPU的速…

一元导数与多元求导数总结

前序&#xff1a;文章结构 1.一元导数 ①一般函数求导 因为太简单的原因&#xff0c;事实上一般函数求导不会单独出现&#xff0c;大多数都是出现在各种特殊的求导过程中。只要掌握16个基本求导公式没问题。 ②复合函数求导&#xff08;主要链式法则&#xff09; 这种一般是…