带你手摸手从零开始撸一个脚手架

本文详细介绍了如何从零开始搭建一个自定义的JavaScript脚手架,包括初始化项目、处理命令行参数、询问用户信息、下载模板代码以及命令行美化等步骤,最终将脚手架发布到npm。通过这个过程,读者可以了解脚手架的工作原理并学会创建自己的脚手架工具。
摘要由CSDN通过智能技术生成

为什么要搭建脚手架

脚手架就是在项目启动的时候询问一些简单的问题,并且通过用户回答的结果去渲染对应的模板文件。

搭建脚手架的目的就是快速搭建项目的基本结构并提供项目规范和约定

目前日常工作中常用的脚手架有 vue-cli、create-react-app、angular-cli 等等,都是通过简单的初始化命令,完成内容的快速构建。

脚手架是我们经常使用的工具,也是团队提效的重要手段,所以系统性的掌握脚手架相关知识,对前端开发者来说是非常重要的。

站在学习的角度,我们创建项目如果只是使用脚手架,我们永远不知道如何搭建一个项目。

👌那这篇文章将手把手教你撸一个属于自己的脚手架!


搭建流程梳理

我们先来看一下脚手架的基本工作流程:

  1. 通过命令行交互询问用户问题
  2. 根据用户回答的结果生成文件

下面呢是我们这次手撸脚手架的步骤:

  • 创建自定义全局命令 npm link

  • 命令参数接受处理 commander

  • 终端交互 inquirer

  • 下载远程代码 download-git-repo

  • 下载等待提示 ora

  • 命令行字体美化 chalk

OK👌,接下来话不多说,直接开撸!


初始化脚手架

我们先来初始化脚手架项目:

mkdir mycli # 新建脚手架项目目录
cd mycli
mkdir bin # 创建 bin 目录
cd bin # 进入 bin 目录
touch cli.js # 新建一个程序入口文件 cli.js 文件
cd ..
npm init # 生成 package.json 文件

此时项目目录结构:

mycli
├─ bin 
	└─ cli.js
└─ package.json  

我们打开 cli.js 文件进行编辑:

#! /usr/bin/env node

// #! 用于指定脚本的解释程序
// Node CLI 应用入口文件必须要有这样的文件头

// 用于检查入口文件是否正常执行
console.log('mycli')

然后我们需要用 npm link 来把这个脚本链接到全局:

sudo npm link

然后我们在命令行输入 mycli,命令行会输入 cli.jslog的内容

在这里插入图片描述


命令参数处理

我们用过很多知名的脚手架,一个成熟的脚手架一定有非常完善的命令参数处理机制。

例如我在这里使用docker --help,控制台会打印:

在这里插入图片描述

接下来我们也来让我们的脚手架实现这样的参数处理功能。

process.argv 属性返回一个数组,这个数组包含了启动 Node.js 进程时的命令行参数

我们在cli.js里打印一下process.argv[2]会得到我们输入的命令行参数

如果我们输入的参数是--help,就打印获取到了help命令参数

// cli.js
if(process.argv[2] == '--help') {
    console.log('获取到了help命令参数');
}

在这里插入图片描述

如果这里通过原生 Node 提供的这个属性去操作命令行中的参数,那肯定是非常的麻烦的,不可能每一个命令我们都自己去实现

所以我们使用第三方提供包,也就是 commander

首先我们npm install commander 来安装commander,然后我们在cli.js引入:

#! /usr/bin/env node

const { program } = require('commander')

console.log(process.argv[2]);

if(process.argv[2] == '--help') {
    console.log('获取到了help命令参数');
}

program.option('-f --framework <framework>','设置框架')
program.parse(process.argv); // parse() 用于解析命名行参数

在这里插入图片描述

我们来优化完善一下配置,增加一个Commands配置用于 create project 创建项目:

program
    .command('create <project> [other...]') // 定义命令
	.alias('crt') // 定义别名
	.description('创建项目') // 描述
	.action((project,args) => { // 定义命令处理方法
    	// 命令行的执行逻辑代码
    	// console.log(project);
    	// console.log(args);
	})

program.parse(process.argv);

在这里插入图片描述

询问用户信息

处理好了命令参数,接下来我们来实现脚手架的询问用户信息的功能

我们这里需要用到inquirer,先来安装一下 npm install inquirer

上面我们写的program.action里面就是命令处理的方法,我们来使用inquirer.prompt来与用户进行信息交互:

program
    .command('create <project> [other...]') // 定义命令
	.alias('crt') // 定义别名
	.description('创建项目') // 描述
	.action((project,args) => { // 定义命令处理方法
    	// 命令行的执行逻辑代码
        inquirer.prompt([
        {
            type: 'input', //type: input, number, list, checkbox ... 
            name: 'username', // key 名
            message: '请输入你的名字', // 提示信息
            // default: 'defaultName' // 默认值
        },
        {
            type: 'list',
            name: 'framework',
            choices: ['express', 'koa', 'egg'],
            message: '请选择你所使用的框架',
        }
    	])
    .then(answer => {
        // 打印用户输入结果
        console.log(answer); // {username:'ruimengmeng',framework:'express'}
    })
	})

program.parse(process.argv);

在这里插入图片描述

下载模版代码

当用户选择完所要用的框架之后,我们就需要从远程仓库下载对应的框架模版代码

download-git-repo 是一个用于下载 GitHub、Gitlab 上的公共仓库的库

我们这里用download-git-repo来实现下载功能,安装npm install download-git-repo,使用方法如下:

    // 下载代码模版
    download(
		'direct:git@gitee.com:xxx/express-template.git',  // 远程仓库的地址
        project,  // './xxx', 下载到本地的路径
        { clone: true },  // 配置参数
        (err) => { // 回调函数
            console.log(err);
        }
    )

好我们来完成下载功能:

program
    .command('create <project> [other...]') // 定义命令
	.alias('crt') // 定义别名
	.description('创建项目') // 描述
	.action((project,args) => { // 定义命令处理方法
    	// 命令行的执行逻辑代码
		const answer = await inquirer.prompt([
            {
                type: 'input',
                name: 'username',
                message: '请输入你的名字',
            },
            {
                type: 'list',
                name: 'framework',
                // choices: ['express', 'koa', 'egg'],
                choices: config.framework,
                message: '请选择你所使用的框架',
            }
    	])
        // .then(answer => {
        //     console.log(answer);
        // })
    
        // 下载代码模版
    	downloadFunction(config.frameworkUrl[answer.framework], project);
	})

const downloadFunction = function (url, project) {
    download(
        "direct:" + url,
        project,
        { clone: true },
        (err) => {
            console.log(err);
        }
    );
};

program.parse(process.argv);

为了代码的可读性和拓展性,我们将选择的框架和框架对应的下载地址放在config.js里:

module.exports = {
    // 可选择的框架
    framework: ['express', 'koa', 'egg'],

    // 框架对应的下载地址
    frameworkUrl: {
        express: 'https://gitee.com/xxx/express-template.git',
        koa: 'https://gitee.com/xxx/koa-template.git',
        egg: 'https://gitee.com/xxx/egg-template.git',
    }
}

我们来试一下我们写的下载功能有没有生效:

在这里插入图片描述

可以看到,选择完框架之后,过了一会框架模版代码成功下载到了bin目录

到目前为止,我们的脚手架基本功能已经实现

但是这个过程非常不友好,没有任何的交互体验可言,就是单纯的用户选择完然后下载,没有任何的下载过程和完成提示

要是网速慢一点,用户简直一脸懵逼,不能忍!我们来优化一下!


等待提示交互

ora 是一个实现命令行 loading 效果的库

安装npm install ora,使用方法如下:

const ora = require('ora')
const spinner = ora().start() // 定义一个loading并启动
spinner.text = 'Loading...'

在这里插入图片描述

使用方法非常简单,接下来我们来添加到我们的脚手架里面:

const downloadFunction = function (url, project) {
    const spinner = ora().start();
    spinner.text = '代码正在下载...';
    // 下载代码模版
    download(
        "direct:" + url,
        project, // './xxx',
        { clone: true },
        (err) => {
            // console.log(err);
            if(!err) {
                spinner.succeed('代码下载成功!🐮');
                console.log('项目已经准备就绪! 😄 你可以运行:');
                console.log('👀 cd ' + project);
                console.log('🌟 npm install ');
                console.log('🔥 npm run dev');
            } else {
                spinner.fail('代码下载失败!🥺')
            }
        }
    );
};

在这里插入图片描述

脚手架命令行美化

chalk 是一个命令行美化工具,能够输出五彩斑斓的命令

// npm install chalk

const chalk = require('chalk');

const downloadFunction = function (url, project) {
    const spinner = ora().start();
    spinner.text = '代码正在下载...';
    // 下载代码模版
    download(
        "direct:" + url,
        project,
        { clone: true },
        (err) => {
            if(!err) {
                spinner.succeed(chalk.green.bold('代码下载成功!🐮'));
                console.log(chalk.blue.bold('项目已经准备就绪! 😄 你可以运行:'));
                console.log(chalk.yellow.bold('👀 cd ' + project));
                console.log(chalk.yellow.bold('🌟 npm install '));
                console.log(chalk.yellow.bold('🔥 npm run dev'));
            } else {
                spinner.fail('代码下载失败!🥺')
            }
        }
    );
};

在这里插入图片描述

到此为止呢,我们的脚手架就算基本完成了

完整代码戳👇此处:https://github.com/KongC-X/mycli

接下来我们就可以将我们的脚手架发布到 npm 上

发布脚手架到npm

第一步:获取 npm 配置

npm config list -l --json

-l 列表表示所有默认配置选项

--json 以 json 格式显示配置选项

这一步是为了确认"registry": "https://registry.npmjs.org/"无误

第二步:登录 npm 账号 npm login

第三步:修改 npm 包版本

更新补丁版本号:npm version patch 0.0.1

更新次要版本号:npm version minor 0.1.1

更新主要版本号:npm version major 1.1.1

第四步:正式发布 sudo npm publish

在这里插入图片描述

发布成功!我们可以在npm官网上找到我们刚刚发布的 npm 包

在这里插入图片描述

我们可以来验证一下:

安装:npm install -g kongccli

测试:kongccli --help

创建项目:kongccli create test-project

在这里插入图片描述

完美!下班!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值