使用nodejs搭建脚手架工具并发布到npm中

使用nodejs搭建脚手架工具并发布到npm中

  • 一、安装环境依赖及脚手架搭建过程
  • 二、搭建Monorepo 风格的脚手架工程
  • 三、脚手架的必备模块
    • 命令参数模块
      • 获取命令参数
      • 设置子命令
    • 用户交互模块
    • 文件拷贝模块
      • 脚手架中的路径处理
      • 目录守卫
    • 文件拷贝模块
    • 动态文件生成模块
      • mustache简介
    • 自动安装依赖模块
    • 发布与安装
  • 四、总结

一、安装环境依赖及脚手架搭建过程

  1. 安装 vue-cli 脚手架:npm install -g vue-cli

  2. 创建项目:vue create myapp
    在这里插入图片描述

  3. 输入cmd:
    在这里插入图片描述

  4. 在cmd中输入:npm init 输入后会生成一个package.json文件
    在这里插入图片描述

  5. 在package.json中添加:./bin/index.js
    在这里插入图片描述

这样就声明了一个mortal命令,而./bin/index.js是运行mortal命令后,所运行js的文件相对路径

  1. 创建bin文件夹、在bin文件夹下创建index.js文件:
    在这里插入图片描述

注意:必须加#!/usr/bin/env node否则会报错

  1. **在cmd窗口执行mortal命令:**会报错
    在这里插入图片描述

报错原因:并不是声明命令的方法错误,而是需要将该脚手架发布到npm上,在package.json中可以看到name值为mortal-cli,所以可以通过运行npm install -g mortal-cli将脚手架安装到本地,再运行mortal才会成功(可理解为安装vue-cli脚手架一样的操作过程)

  1. **实现在本地调试脚手架的能力:**先执行npm link再执行mortal则运行成功
    在这里插入图片描述

**总结:**到此一个声明命令结束
注意: npm link的弊端:若本地存在多个版本的脚手架仓库,在A仓库中修改代码,然后运行mortal命令,会发现所修改的代码并不生效。原因是:在仓库B的脚手架中已经运行了npm link,从而导致再次运行mortal时实际上是执行仓库B中的代码。所以要先在仓库B的脚手架工程中先进行释放,运行npm unlink,然后再在仓库A中执行npm linkmortal,此时仓库A中已经修改的代码会生效。所以可以通过pnpm来搭建monorepo风格的脚手架工程。
Monorepo风格:即代码管理方式,指单个仓库中管理多个项目,有助于简化代码共享、版本控制、构建和部署等方面的复杂性,并提供更好的可重用性和协作性。含有多个子工程,每一个子工程都能独立编译打包,并将产物变成npm包,所以又叫monorepo为多包工程。

  1. 修改package.json以便于更好的发布到npm上:
    在这里插入图片描述

注意:在dependencies中声明mortal-cli依赖包版本需使用workspace:*来定义,而不是使用具体的版本号来定义。
在 pnpm 中使用 workspace: 协议定义某个依赖包版本号时,pnpm 将只解析存在工作空间内的依赖包,不会去下载解析 npm 上的依赖包。
把 mortal-cli 依赖包引入,执行 pnpm i 安装依赖,其效果就跟执行 npm install -g mortal-cli一样,只不过不是全局安装而已,只在调试子工程内安装 mortal-cli 脚手架。然后调试子工程就直接引用脚手架子工程本地编译打包后的产物,而不是发布到 npm 上的产物,彻底做到本地调试。
另外脚手架子工程和调试子工程是在同一个工程中,这样就做一对一的调试,从而解决了使用 npm link 来实现本地调试的弊端。
同时在 scripts 定义了脚本命令,在调试工程中执行 pnpm mortal 既是执行了 mortal 命令,不用脚手架工程中执行 npm link 就可以运行 mortal 命令。

  1. **安装pnpm:**先安装pnpm安装pnpm地址详细请见该文章 安装命令:iwr https://get.pnpm.io/install.ps1 -useb | iex
    在这里插入图片描述

二、搭建Monorepo 风格的脚手架工程

  1. 新建mortal文件夹:
    在这里插入图片描述

  2. 使用pnpm搭建monorepo风格脚手架:pnpm init
    在这里插入图片描述

  3. 创建pnpm-workspace.yaml工作空间配置文件: 并添加以下代码
    在这里插入图片描述

声明了 packages 和 examples 文件夹中子工程是同属一个工作空间的,工作空间中的子工程编译打包的产物都可以被其它子工程引用。
在这里插入图片描述

  1. 使用pnpm初始化:pnpm init在packages文件夹下的mortal文件夹下产生一个package.json文件
    在这里插入图片描述
    在这里插入图片描述

  2. 在package.json文件中新建bin字段声明mortal
    在这里插入图片描述

  3. 在packages->mortal下新建bin文件夹,在bin文件夹下新建index.js文件
    在这里插入图片描述

  4. 在与packages同级目录下新建examples文件夹,在该文件夹下创建app文件夹 输入cmd,再输入pnpm init进行初始化生成package.json文件
    在这里插入图片描述
    在这里插入图片描述

  5. 给example文件夹中的package.json添加代码:
    在这里插入图片描述

  6. 在最外层的根目录执行安装命令:pnpm install
    在这里插入图片描述

  7. 当前的目录结构:

Project Tree插件可生成tree目录,或者在该文件夹中cmd到根目录->输入TREE>文件名.txt也可生成tree目录
使用Project Tree插件:Crtl + Shift + P -> 输入Project Tree->生成README.md文件这里是引用
在这里插入图片描述
这里是目录工程化
在这里插入图片描述

// 当前项目的目录结构如下所示:
mortal
├─ examples
│  └─ app
│     └─ package.json
├─ package.json
├─ packages
│  └─ mortal-cli
│     ├─ bin
│     │  └─ index.js
│     └─ package.json
├─ pnpm-lock.yaml
└─ pnpm-workspace.yaml

三、脚手架的必备模块

命令参数模块

获取命令参数

  1. Node.js 中的 process 模块提供了当前 Node.js 进程相关的全局环境信息,比如命令参数、环境变量、命令运行路径process模块 安装命令:npm install
const process = require('process');
// 获取命令参数
console.log(process.argv); 

脚手架提供的 mortal 命令后面还可以设置参数,标准的脚手架命令参数需要支持两种格式:

mortal --name=orderPage
mortal --name orderPage

通过 process.argv 来获取,要额外处理两种不同的命令参数格式不方便,这里使用 yargs 开发脚手架/CLI,这里推荐 yargs 开源库来解析命令参数

  1. 这里使用 yargs 开发脚手架/CLI:pnpm add yargs --F mortal-cli
    在这里插入图片描述

这里要注意,mortal-cli 是取 mortal-cli 子工程中 package.json 中 name 字段的值,而不是 mortal-cli 子工程文件夹的名称。yargs 的使用非常简单,其提供的 argv 属性是对两个格式的命令参数的处理结果。

  1. 在 bin/index.js 添加如下代码:
#!/usr/bin/env node
const yargs = require('yargs')

console.log('name',yargs.argv.name);

在这里插入图片描述

注意,以上代码是在 Node.js 环境中运行,Node.js 的模块是遵循 CommonJS 规范的,如果要依赖一个模块,要使用 Node.js 内置 require 系统函数引用模块使用。

  1. 在example/app文件夹下执行:pnpm mortal -- --name=orderPage
    在这里插入图片描述

注意,在 pnpm mortal 后面需要加上两个连字符(--),这是为了告诉 pnpm 后面的参数是传递给命令mortal 本身的,而不是传递给 pnpm 的。结果是name orderPage

设置子命令

假如脚手架要对外提供多个功能,不能将所有的功能都集中在 mortal 命令中实现。可通过 yargs 提供的 command 方法来设置一些子命令,让每个子命令对应各自功能,各司其职。
yargs.command 的用法是 yargs.command(cmd, desc, builder, handler)

  • cmd:字符串,子命令名称,也可以传递数组,如 [‘create’, ‘c’],表示子命令叫 create,其别名是 c;
  • desc:字符串,子命令描述信息;
  • builder:一个返回数组的函数,子命令参数信息配置,比如可以设置参数:
    • alias:别名;
    • demand:是否必填;
    • default:默认值;
    • describe:描述信息;
    • type:参数类型,string | boolean | number。
  • handler: 函数,可以在这个函数中专门处理该子命令参数。

设置一个用来生成一个模板的子命令,把这个子命令命名为create: 修改在 bin/index.js 文件中的代码:

#!/usr/bin/env node
//

const yargs = require('yargs');
yargs.command(
  ['create', 'c'],
  '新建一个模板',
  function (yargs) {
   
    return yargs.option('name', {
   
      alias: 'n',
      demand: true,
      describe: '模板名称',
      type: 'string'
    })
  },
  function (argv) {
   
    console.log('argv', argv);
  }
).argv;

在app下执行:pnpm mortal create -- --name=orderPagepnpm mortal c -- --name=orderPage
在这里插入图片描述

配置了子命令 create 的参数 name 的一些参数信息,如何将这些信息展示给用户:输入子命令的参数有错误,就会在命令行窗口中显示这些参数信息。

在app文件夹目录下:pnpm mortal c -- --abc
在这里插入图片描述

最简单地实现了脚手架和用户之间的交互能力,但是如果自定义参数过多,那么命令行参数的交互方法对于用户来说是非常不友好的。所以需要通过用户交互模块桥接与用户进行交互。

用户交互模块

  1. 下载inquirer: 实现询问式的交互 pnpm add inquirer@8.2.5 --F mortal-cli
    在这里插入图片描述

为了使用 require 引入 inquirer ,要使用 8.2.5 版本的 inquirer。
inquirer 能力:询问用户问题、获取并解析用户的输入、检测用户的答案是否合法

主要通过 inquirer.prompt() 来实现。prompt 函数接收一个数组,数组的每一项都是一个询问项,询问项有很多配置参数,下面是常用的配置项:

  • type:提问的类型,常用的有:
    • 输入框:input;
    • 确认:confirm;
    • 单选组:list;
    • 多选组:checkbox;
  • name:存储当前问题答案的变量;
  • message:问题的描述;
  • default:默认值;
  • choices:列表选项,在某些type下可用;
  • validate:对用户的答案进行校验;
  • filter:对用户的答案进行过滤处理,返回处理后的值。

总结:创建一个模板文件,大概会询问用户:模板文件名称、模板类型、使用什么框架开发、使用框架对应的哪个组件库开发等等

  1. 在 bin 文件夹中新建 inquirer.js 文件夹:
// 添加的内容
const inquirer = require("inquirer");

function inquirerPrompt(argv) {
   
  const {
    name } = argv;
  return new Promise((resolve, reject) => {
   
    inquirer
      .prompt([
        {
   
          type: "input",
          name: "name",
          message: "模板名称",
          default: name,
          validate: function (val) {
   
            if (!/^[a-zA-Z]+$/.test(val)) {
   
              return "模板名称只能含有英文";
            }
            if (!/^[A-Z]/.test(val)) {
   
              return "模板名称首字母必须大写";
            }
            return true;
          },
        },
        {
   
          type: "list",
          name: "type",
          message: "模板类型",
          choices: ["表单", "动态表单", "嵌套表单"],
          filter: function (value) {
   
            return {
   
              表单: "form",
              动态表单: "dynamicForm",
              嵌套表单: "nestedForm",
            }[value];
          },
        },
        {
   
          type: "list",
          message: "使用什么框架开发",
          choices: ["react", "vue"],
          name: "frame",
        },
      ])
      .then((answers) => {
   
        const {
    frame } = answers;
        if (frame === "react") {
   
          inquirer
            .prompt([
              {
   
                type: "list",
                message: "使用什么UI组件库开发",
                choices: ["Ant Design"],
                name: "library",
              },
            

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

libVLC 提取视频帧

在前面的文章中,我们使用libvlc_media_player_set_hwnd设置了视频的显示的窗口。 libvlc_media_player_set_hwnd(vlc_mediaPlayer, (void *)ui.widgetShow->winId()); 如果我们想要提取每一帧数据,将数据保存到本地,该如何操作呢&#x…

017——DS18B20驱动开发(基于I.MX6uLL)

目录 一、 模块介绍 1.1 简介 1.2 主要特点 1.3 存储器介绍 1.4 时序 1.5 命令 1.5.1 命令大全 1.5.2 命令使用 1.5.3 使用示例 1.6 原理图 二、 驱动程序 三、 应用程序 四、 测试 一、 模块介绍 1.1 简介 DS18B20 温度传感器具有线路简单、体积小的特点&…

mysql慢sql排查与分析

当MySQL遇到慢查询(慢SQL)时,我们可以通过以下步骤进行排查和优化: 标题开启慢查询日志: 确保MySQL的慢查询日志已经开启。通过查看slow_query_log和slow_query_log_file变量来确认。 如果没有开启,可以…

关于Ansible模块 ⑤

转载说明:如果您喜欢这篇文章并打算转载它,请私信作者取得授权。感谢您喜爱本文,请文明转载,谢谢。 继《关于Ansible的模块 ①》、《关于Ansible的模块 ②》与《关于Ansible的模块 ③》之后,继续学习ansible常用模块之…

数据结构算法题 2(力扣)——链表

1. 分割链表(OJ链接) 题目描述:给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有小于 x 的节点都出现在大于或等于 x 的节点之前。 本题做法是:遍历链表将链表分为两部分&#xf…

Discord注册教程:Discord刚注册就被封怎么办?附申诉教程!

Discord如今在海外社交媒体平台中迅速崛起,许多社交媒体营销人员也纷纷利用其社群特性进行推广,Discord注册也就成为社媒营销人员必经之路。然而,很多人注册Discord账号时常常会想:“在国内使用Discord会封号吗?”事实…

STC12单片机设置50Hz的PWM波驱动舵机

本文将使用STC12C5A60S2配置PWM波,驱动SG90舵机。 采用的开发板包括了CH340芯片,因此下载程序只需要使用MicroUSB转USB连接线使用STC-ISP.exe软件下载程序即可。 1 芯片资源 芯片型号STC12C5A60S2,增强型8051 CPU,1T&#xff0c…

计算机组成原理 — CPU 的结构和功能

CPU 的结构和功能 CPU 的结构和功能CPU 概述控制器概述CPU 框架图CPU 寄存器控制单元 CU 指令周期概述指令周期的数据流 指令流水概述指令流水的原理影响流水线性能的因素流水线的性能流水线的多发技术流水线结构 中断系统概述中断请求标记和中断判优逻辑中断请求标记 INTR中断…

Mysql底层原理五:如何设计、用好索引

1.索引的代价 空间上的代价 时间上的代价 每次对表中的数据进⾏增、删、改操作时,都需要去修改各个B树索引。⽽且我们讲过,B树每层节点都是按照索引列的值从⼩到⼤的顺序排序⽽组成了双 向链表。不论是叶⼦节点中的记录,还是内节点中的记录&a…

设计模式实践

一、工厂模式 这里只讲简单工厂模式,详细的可以参考Java工厂模式(随笔)-CSDN博客。工厂类会根据不同的参数或条件来决定创建哪种对象,这样客户端只需要知道自己需要什么对象,而不需要关心对象的创建过程! …

Golang 开发实战day06 - Boolean Conditional

🏆个人专栏 🤺 leetcode 🧗 Leetcode Prime 🏇 Golang20天教程 🚴‍♂️ Java问题收集园地 🌴 成长感悟 欢迎大家观看,不执着于追求顶峰,只享受探索过程 Golang 教程06 - Boolean &a…

分布式锁的原子性问题

4.6 分布式锁的原子性问题 更为极端的误删逻辑说明: 线程1现在持有锁之后,在执行业务逻辑过程中,他正准备删除锁,而且已经走到了条件判断的过程中,比如他已经拿到了当前这把锁确实是属于他自己的,正准备删…

如何在CentOS安装Nexus容器无公网IP远程管理本地仓库

文章目录 1. Docker安装Nexus2. 本地访问Nexus3. Linux安装Cpolar4. 配置Nexus界面公网地址5. 远程访问 Nexus界面6. 固定Nexus公网地址7. 固定地址访问Nexus Nexus是一个仓库管理工具,用于管理和组织软件构建过程中的依赖项和构件。它与Maven密切相关,可…

数据通讯平台解决方案(Word原件获取)

1.数据通讯平台方案 1.1.系统概述 1.2.需求分析 1.3.重难点分析 1.4.重难点解决措施 2.系统架构设计 2.1.系统架构图 系统机构图 2.2.业务架构设计 (1) MQ消息服务 (2) TCP通讯服务 (3) CoAP通讯服务 (4) MQTT通讯服务 (5) 资源管理服务 2.3.主流技术架构分析 纵向设计方案 2.4…

QGraphics框架场景中图元的移除与析构

1.场景里面使用removeItem函数,这个函数官方给出如下解释 注意这个词remove只是移除,并不是delete掉,所以只是场景中(显示出来的图元)没有了,空间还是存在。 举个代码例子: void MyGraphicsV…

USACO 2024 Open Bronze铜组题解

迟到了一个月的题解...... Logical Moos: 啊这题放在铜组T1雀食有点BT...... 首先,我们关注l前第一和r最后那两组。如果这俩有一个是true,那答案肯定也是true。 否则,在l和r外边的都是false。那我们就只用仔细看l和r中间的玩意儿。对于l和…

三月以来的黄金暴涨 ,华尔街都看不懂

本轮黄金大幅上涨无法按照美联储政策逻辑解释,央行的购金需求也无法合理化金价的历史新高,而金价的大涨也与黄金ETF流出相背,推动反弹的“神秘力量”令分析师困惑不已。 黄金上涨的情况往往会出现在美联储开启降息周期后,如果市场…

Linux 之 定时任务调度器-crond(crontab)服务

Linux系列文章: Windows本地如何添加域名映射?(修改hosts文件)_本机域名映射-CSDN博客 Linux安装mysq 8.0服务端和客户端(亲测保成功)_linux安装mysql客户端-CSDN博客 linux-man命令的使用及练习_man命令执行后无法…

微服务架构下,如何通过弱依赖原则保障系统高可用?

前言 当我初次接触高可用这个概念的时候,对高可用的【少依赖原则】和【弱依赖原则】的边界感模糊,甚至有些“傻傻分不清楚”。这两个原则都关注降低模块之间的依赖关系,但它们之间的确存在某些差异。 那么,「少依赖原则」和「弱…

Windows深度学习环境----Cuda version 10.2 pytorch3d version 0.3.0

Requirements Python version 3.8.5Pytorch version: pytorch1.6.0 torchvision0.8.2 torchaudio0.7.0 cudatoolkit10.2.89pytorch3d version 0.3.0Cuda version 10.2 感觉readme文件里的不适配,跟pytorch官网不同 以前的 PyTorch 版本 |PyTorch的 # CUDA 10.2 c…