如何理解基础构建--前端脚手架

370 阅读4分钟

本篇文章主要给大家介绍如何开发一个自己的前端脚手架,用来快速的创建模板和项目。

1.初始化项目文件

mkdir template-create //创建文件夹
cd template-create //进入该目录
npm init -y //创建一个package.json

使用以上的命令对项目进行文件的创建

创建一个package.json

创建文件和文件结构

bin
  index.js
index.js
​
#!/usr/bin/env node
//该文件可以用node去执行console.log(123);
//可以用命令 node ./bin/index.js来运行

使用其他方式来进行文件的运行

(1)配置package.json

"bin":"/bin/index.js"

(2)使用npm link链接到全局,npm i -g表示将某个插件下载到全局,而npm link则是将我们本地开发的插件连接到本地的全局

{
  "name": "template-create",
  "version": "1.0.0",
  "main": "index.js",
  "bin": "/bin/index.js",
  "scripts": {
    "test": "echo "Error: no test specified" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}
​
​

(3)当我们link完了之后就可以直接使用该name进行文件的运行

template-create

当npm link之后 如果文件发生什么变化 会及时的更新

2.相关包的使用和介绍

commander:命令行的处理工具

npm i commander

(1)引入:

#!/usr/bin/env node
// 该文件可以用 node 去执行const { program } = require('commander');
​
// 定义程序名称和用法
program.name('template-create').usage('<command> [option]')
  .description('A CLI tool for managing templates');
​
// 定义 `--version` 选项
program.option('-v, --version', 'tell the template version')
  .action(() => {
    console.log('Template version: 1.0.0');
  });
​
// 定义 `clone` 命令
program.command('clone <source> [destination]')
  .description('Clone a repository into a newly created directory')
  .action((source, destination) => {
    console.log('Source:', source);
    console.log('Destination:', destination);
  });
​
// 解析命令行参数
program.parse(process.argv);
​
// 获取所有选项
const options = program.opts();
console.log(options);
​

chalk:命令行的样式的工具

npm i chalk@4.0.0
//由于最新的模块是基于ESM,此工程的引用使用的是CJS,所以下载4的版本
const chalk = require('chalk')
//---------------------chalk----------------------console.log(chalk.red(123));
//可以用Chalk来控制命令行中命令的颜色

inquire:命令行的交互的工具

npm i inquirer@8.0.0
​
inquirer
    .prompt([
        {
            type:'input',//选项的类型
            name:'food',//选项的键名
            message:'what do you want to eat?',//提示信息
            default:'Hamburger'//默认值
        },
     {
            type:'confirm',
            name:'hot',
            message:'Do you eat spicy food?',
            default:false
        },
    ])
    .then((answer)=>{
        console.log(answer)//答应输入
    })
    .catch((error)=>{
        if(error.isTtyError){
            
            console.log('input error');//提示错误
        }
    })
​

ora:终端loading美化工具

​
npm i ora@5.0.0
​
const spinner = ora('Loading...').start()//创建一个开始的实例
setTimeout(()=>{
    spinner.text = 'Network loading...';//加载过程的提示
    spinner.color='red';//加载样式改变
},2000)
setTimeout(()=>{
    spinner.succeed('Success!');//成功
    spinner.fail('Network error');
    spinner.color='green';
},4000)
​

gitclone:下载模板的工具

figlet:终端生成艺术字体

figlet('Wang shi yi is a beauty!',function(err,data){
    if(err){
        console.log('Something went wrong...');
        console.log(err);
        return;
    }
    console.log(data)
});

fs:用来操作本地目录

gitClone(repository, destination, options, callback)
 gitClone(repoURL, name, { checkout: 'main' }, function (err){
     
 })
  • repository: Git 仓库的 URL,支持 HTTP(S) 和 SSH 协议。

  • destination: 克隆到的本地路径(目录)。

  • options

    : 选项对象,支持以下字段:

    • checkout: 指定要检出的分支(例如 maindevelop)。如果不指定,默认会克隆整个仓库。
  • callback: 克隆完成后的回调函数,接受一个错误对象作为参数。如果克隆成功,errnull,否则为错误对象。

开发步骤

1. 导入相关的库

const { program } = require('commander');//创建命令
const figlet = require("figlet");//艺术字体
const chalk = require("chalk");//命令行样式
const fs = require('fs-extra');//路径的输入
const path = require('path');//路径
const inquirer = require('inquirer');//捕获用户的输入
const gitClone = require('git-clone');//远程clone
const ora = require('ora');//等待

2.使用commander库来进行创建

// 首行提示
program
    .name('template-create')
    .usage('<command> [option]')//尖括号必填 方括号选填
    .description(chalk.green('一个快速并便利的模板创建脚手架!'));
​
// 版本
program.version(`v${require('../package.json').version}`);
​
//对命令进行说明
//对包的版本和package.json中的文件进行绑定

3.创建clone的命令

//创建项目的命令
program.command('create <app-name>')
    .description('Clone a repository into a newly created directory')
    .action(async (name) => {
        //1.拿到当前目录
       const targetPath = path.join(process.cwd(),name);
       //2.判断是否存在
        if(fs.pathExistsSync(targetPath))
        {
            //3.用一个常量来接收输入的结果
            const answer = await inquirer.prompt([
                {
                    type:'confirm',
                    message:chalk.red('该目录下已存在相同文件名的文件是否进行覆盖?'),
                    default:false,
                    name:'overwrite'
                }
​
            ])
            //4.对常量中的overwrite的布尔值进行判断
            if(answer.overwrite){
                fs.remove(targetPath);
                console.log(chalk.green('删除成功!'));
            }
        }
​
        //5.新建一个项目
​
        const result = await inquirer.prompt([
            {
                type:'list',
                name:'type',
                message:'请选择你要创建的模板:',
                choices:[
                    {
                        name:'vue',
                        value:'vue'
                    },
                    {
                        name:'react',
                        value:'react'
                    }
                ]
​
            },
            {
                type:'list',
                name:'ts',
                message:'是否使用TypeScript',
                choices:[
                    {
                        name:'是',
                        value:true
                    },
                    {
                        name:'否',
                        value:false
                    }
                    ]
​
            }
            ])
    console.log(result);
    const key = result.type+(result.ts?'&ts':'');
    console.log(key);
    const repoURL = ProjectList[key];
        const spinner = ora(chalk.yellow('正在下载模板,请稍候...')).start(); // 显示加载动画
​
        gitClone(repoURL, name, { checkout: 'main' }, function (err) {
            if (err) {
                // 下载失败
                spinner.fail(chalk.red('模板下载失败,请检查仓库地址是否正确!'));
                console.error(chalk.red('错误信息:'), err.message);
            } else {
                // 下载成功
                spinner.succeed(chalk.green('模板下载成功!'));
                fs.remove(path.join(targetPath,'.git'));
                console.log(chalk.green('项目已成功创建,请执行以下的操作:'));
                console.log(chalk.green(`\n cd ${name}`));
                console.log(chalk.green(`npm install`));
                console.log(chalk.green(`npm run dev\n`));
            }
        });
​
    });

(1).获取路径 并查看当前目录下是否存在相同名称的文件

  //1.拿到当前目录
       const targetPath = path.join(process.cwd(),name);
       //2.判断是否存在
        if(fs.pathExistsSync(targetPath))
        {
            //3.用一个常量来接收输入的结果
            const answer = await inquirer.prompt([
                {
                    type:'confirm',
                    message:chalk.red('该目录下已存在相同文件名的文件是否进行覆盖?'),
                    default:false,
                    name:'overwrite'
                }
​
            ])
            //4.对常量中的overwrite的布尔值进行判断
            if(answer.overwrite){
                fs.remove(targetPath);
                console.log(chalk.green('删除成功!'));
            }
        }
​

(2).如果不存在的话就获取用户的输入使用inquirie库来进行交互和输入结果的捕获

 //5.新建一个项目
​
        const result = await inquirer.prompt([
            {
                type:'list',
                name:'type',
                message:'请选择你要创建的模板:',
                choices:[
                    {
                        name:'vue',
                        value:'vue'
                    },
                    {
                        name:'react',
                        value:'react'
                    }
                ]
​
            },
            {
                type:'list',
                name:'ts',
                message:'是否使用TypeScript',
                choices:[
                    {
                        name:'是',
                        value:true
                    },
                    {
                        name:'否',
                        value:false
                    }
                    ]
​
            }
            ])
    console.log(result);
    const key = result.type+(result.ts?'&ts':'');
    console.log(key);

(3).创建一个对象里面用来写清楚要clone的模板的键值对,键为用户的输入,值为clone的仓库地址

const ProjectList={
​
        'vue':'git@github.com:kfc-vme50/vue-template.git',
        'react':'git@github.com:kfc-vme50/vue-template.git',
        'vue&ts':'git@github.com:kfc-vme50/vue-template-ts.git',
        'react&ts':'git@github.com:kfc-vme50/vue-template-ts.git',
​
    }
​

(4).使用getClone的方法进行远程的clone

const repoURL = ProjectList[key];
        const spinner = ora(chalk.yellow('正在下载模板,请稍候...')).start(); // 显示加载动画
​
        gitClone(repoURL, name, { checkout: 'main' }, function (err) {
            if (err) {
                // 下载失败
                spinner.fail(chalk.red('模板下载失败,请检查仓库地址是否正确!'));
                console.error(chalk.red('错误信息:'), err.message);
            } else {
                // 下载成功
                spinner.succeed(chalk.green('模板下载成功!'));
                fs.remove(path.join(targetPath,'.git'));
                console.log(chalk.green('项目已成功创建,请执行以下的操作:'));
                console.log(chalk.green(`\n cd ${name}`));
                console.log(chalk.green(`npm install`));
                console.log(chalk.green(`npm run dev\n`));
            }
        });

4.NPM发布

1.创建一个NPM的账号

2.npm login

3.npm publish

发布过程中如果出现403代表有重复的名称

只需要修改package.json里面的文件即可