脚手架构建

1. 引言

背景介绍

前端脚手架的目的在于提高前端开发的效率和一致性 ,节约一些重复性工作,例如:编译、打包、代码检查,避免了从零开始搭建项目框架的繁琐工作。

需求分析: 

  • 项目创建与初始化
    • 创建新的项目目录结构。
    • 初始化基本的项目文件,如index.htmlpackage.json等。
  • 依赖安装
    • 自动安装项目所需的核心依赖。
    • 支持选择性安装额外的依赖或插件。
  • 用户交互
    • 提供命令行界面,让用户能够输入项目配置信息。
    • 根据用户输入生成定制化的项目配置。
  • 模板生成
    • 根据用户的选择生成基础的项目模板。
    • 支持多种预设模板以适应不同的项目类型。
  • 架构设计
    • 包括命令行解析模块、模板管理模块、文件生成模块等,并解释每个模块的作用和它们之间的交互。

2. 相关工具介绍

(📗代表核心工具,📒代表辅助工具)

命令行交互

  • 📗 commander:Commander.js 中文网
  • 📗 inquirer:选项命令行交互工具
  • 📒 chalk:美化命令行输出
  • 📒 figlet:创建 ASCII 艺术字
  • 📒 ora:加载指示器

下载模板

  • 📗 git-clone:用于创建任何可通过网络访问的 Git 仓库的副本
  • 📗 npminstall: 可以用来安装依赖包,将安装的依赖包名称及版本信息添加到项目的 package.json 文件中

文件操作

  • 📗 fs-extra:扩展 Node.js 原生 fs 模块功能的库,支持 Promise、防止 EMFILE 错误,并包含复制、移动、确保目录存在等常用操作

4. 实现脚手架

以下是一个简单的脚手架结构示例:

scaffold/
├── package.json
├── jsconfig.json
├── babel.config.js
└── bin/├── index.js
└── src/├── commands├── create.js└── ...├── lib├── consts.js├── index.js├── logger.js├── spinner.js└── ...

创建 package.json

package.json 文件中,你需要定义脚手架的元数据和依赖项:

{"name": "demo-cli","version": "1.0.0","description": "","main": "index.js","bin": "./bin/index.js","scripts": {"test": "echo \"Error: no test specified\" && exit 1"},"keywords": [],"author": "","license": "ISC","dependencies": {"chalk": "^4.0.0","commander": "^12.1.0","figlet": "^1.7.0","fs-extra": "^11.2.0","git-clone": "^0.2.0","inquirer": "^8.0.0","npminstall": "^7.6.0","ora": "^5.0.0"},"devDependencies": {"@babel/cli": "^7.23.4","@babel/core": "^7.25.2","@babel/plugin-proposal-object-rest-spread": "^7.20.7","@babel/preset-env": "^7.24.7"}
}

实现 index.js

index.js 是脚手架的入口文件,它将处理用户输入和脚手架的逻辑流程:

#!/usr/bin/env nodeconst { program } = require('commander');
const pkg = require('../package.json');
const chalk = require('chalk');
const inquirer = require('inquirer');
const ora = require('ora');
const figlet = require('figlet');
const { info, warn, error } = require('../src/lib/logger');
const { startSpinner, succeedSpiner, failSpinner } = require('../src/lib/spinner');
const createAction = require('../src/commands/create');// figlet('KFC Crazy Thursday V Me 50 !!!', (err, data) => {
//   if (err) {
//     console.log('Something went wrong...');
//     console.dir(err);
//     return;
//   }
//   console.log(chalk.green(data));
// });// const spinner = ora('loading ...').start();program.name('demo-cli').usage('<command> [options]');
program.version(`v${pkg.version}`);
program.on('--help', () => {console.log();console.log('  Examples:');console.log();console.log('    $ demo-cli create <project-name>');console.log('    $ demo-cli <command> [options]');
});
program.command('create <name>').description('create a new project').action((name) => {createAction(name);});program.parse(process.argv);// const options = program.opts();
// console.log(options);// console.log('肯德基疯狂星期四,V我50!');

实现 create.js

create.js 它将处理用户输入和脚手架的逻辑流程:

const path = require('path');
const fs = require('fs-extra');
const inquirer = require('inquirer');
const chalk = require('chalk');
const { startSpinner, succeedSpiner, failSpinner } = require('../lib/spinner');
const { info, warn, error } = require('../lib/logger');
const { cwd, reactRepo, vueRepo } = require('../lib/consts');
const gitCLone = require('git-clone');const checkProjectExist = async (targetDir) => {if (fs.existsSync(targetDir)) {const answer = await inquirer.prompt({type: 'list',name: 'checkExist',message: `\n仓库路径${targetDir}已存在,请选择`,choices: ['覆盖', '取消'],});if (answer.checkExist === '覆盖') {warn(`删除${targetDir}...`);fs.removeSync(targetDir);} else {return true;}}return false;
};const getQuestions = async (projectName) => {return await inquirer.prompt([{type: 'input',name: 'name',message: `project name: (${projectName})`,default: projectName,},{type: 'rawlist',name: 'frame',message: '选择所用框架:',choices: ['React', 'Vue'],default: 'React',},{type: 'checkbox',name: 'enosDependencies',message: '请选择所用依赖:',choices: [{ name: 'antd', value: 'antd' },{ name: '***SDK', value: '***SDK' },],},// {//   type: 'confirm',//   name: 'antd',//   message: '是否集成antd:',//   default: false,// },]);
};const createProject = async (targetDir, projectInfo) => {console.log(projectInfo);const repo = projectInfo.frame === 'React' ? reactRepo : vueRepo;startSpinner('下载react仓库...');gitCLone(repo, targetDir, { checkout: 'main' }, (err) => {if (err) {failSpinner(err);return;}succeedSpiner(`项目创建完成 ${chalk.yellow(projectInfo.name)}\n👉 输入以下命令进入项目:`);info(`$ cd ${projectInfo.name}\n `);});
};const action = async (projectName, cmdArgs) => {try {const targetDir = path.join((cmdArgs && cmdArgs.context) || cwd, projectName);if (!(await checkProjectExist(targetDir))) {const projectInfo = await getQuestions(projectName);await createProject(targetDir, projectInfo);}} catch (err) {failSpinner(err);return;}
};module.exports = action;

 

5. 测试脚手架

  • 本地测试
    • 使用npm link进行本地测试,以便在全局环境中测试你的脚手架。
    • 然后,你可以使用以下命令来创建新项目:
demo-cli create test-project

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

07. 按钮控件

一、按钮控件PySide6 中按钮分为 push 按钮(按压型)、check 按钮(勾选型)和 toggle 按钮(切换型,多个按钮中只有一个可以选中)。其中,push 按钮有 QPushButton 按钮和 QToolButton 按钮,check 按钮是 QCheckBox 按钮,toggle 按钮是 QRadioButton,它们都继承自 QAbas…

opencascade配置笔记

下载occ 网址参考网址 c++引用lib库 参考网址 vs使用qt插件 参考网址 参考网址

大规模可观测性揭秘:Netflix 如何通过标题玩转全球内容发布?

1 导言 在 Netflix,我们每月管理着上千个全球内容发布项目,每年的投资额高达数十亿美元。确保每部影片在我们平台上的成功和可发现性是我们的首要任务,因为我们的目标是将每个故事与合适的受众联系起来,让我们的会员满意。为了实现这一目标,我们致力于建立强大的系统,提…

Netty的高性能之道

一、概述 1.1 惊人的性能数据 最近一个圈内朋友通过私信告诉我,通过使用Netty4 + Thrift压缩二进制编解码技术,他们实现了10W TPS(1K的复杂POJO对象)的跨节点远程服务调用。相比于传统基于Java序列化+BIO(同步阻塞IO)的通信框架,性能提升了8倍多。 事实上,我对这个数据…

javaweb实战02

javaweb实战02 本次开始配置目录和包以及构建数据库然后就可以按照业务逻辑书写页面,页面包含登录和注册两个功能 首先开发登录页面 <%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ page isELIgnored="false"…

1大模型应用开发基础

一、目标 懂得AI,懂得编程、懂得业务的超级个体,将会是AGI时代最重要的人。 AI使得一个人能够干多个人的活 想要做到“AI全栈”需要涉及的知识面是非常广泛的,单单学习一门课程是不能全部涉及的 我们首先需要做的是入门,后面走的深入,走的远只能靠自己,依靠社群,和AI的进…

grpc安装(windows or Linux)

grpc安装(windows or Linux) 下载源码 这里使用 gRPC 最新版本源代码进行编译和安装,版本号为 v1.50.0, 以下为安装步骤: 一、使用Git克隆gRPC到本地 在终端中打开某一文件夹,建议新建一个单独存放 gRPC 源代码的文件夹,输入: git clone -b v1.50.0 https://github.com/…

Golang内存模型与源码解析

0、引言 本篇笔记用于记录作者在学习Golang的GC模型之前,对Golang内存模型的学习。目前使用的Go版本为1.22.4 1、Golang内存管理宏观结构 假设我们每次向内存池申请空间时,都需要频繁地向操作系统发出请求,这不仅会增加内存分配的时间,还可能引入竞争和锁的开销,从而导致性…

图床试验

本文来自博客园,作者:Glowingfire,转载请注明原文链接:https://www.cnblogs.com/Glowingfire/p/18617999

一文搞定理解RPC

前言RPC概念RPC协议RPC组成RPC协议RPC框架RPC的优点RPC与HTTP的区别 前言 RPC的概念相信很多软件从业人员或多或少都接触过,从开发到测试都可能需要跟它打交道。 但是对于为什么要用RPC?RPC的优点是什么?RPC是什么原理?它跟HTTP有什么不同?相信并不是每个人都比较熟悉。 那…

全场景一站式2024最新vmware环境下安装win7并且破解QTP

目录VMwareVMware和Ubuntu下载链接下载Win 7 系统各个操作系统网站激活码是什么查看是否激活激活操作vmware下安装ubuntu创建虚拟机下载VMtool灰色灰色按键点击不了下载提示有问题原因文件传递共享文件借助外界U盘有了VMTool就可以直接拖拽!!!!有了VMTool就可以全屏化——倒…