使用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",},

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

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

相关文章

思迈特软件与上海德拓签署战略合作协议,携手赋能企业数字化转型

3月27日,广州思迈特软件有限公司(简称“思迈特软件”)与上海德拓信息技术有限公司(简称“德拓信息”)正式签约建立战略合作伙伴关系。双方将在数字化转型、数据服务、数据应用以及市场资源等多个领域展开深度合作&…

基于机器学习的信用卡办卡意愿模型预测项目

基于机器学习的信用卡办卡意愿模型预测项目 在金融领域,了解客户的信用卡办卡意愿对于银行和金融机构至关重要。借助机器学习技术,我们可以根据客户的历史数据和行为模式预测其是否有办理信用卡的倾向。本项目通过Python中的机器学习库,构建…

CSS变换

CSS变换 根据 CSS 的变换的功能特性,它可以分为位移、旋转、缩放、倾斜和透视: 也可以分成2D变换和3D变换,2D变换是二维平面上进行的,即 X 轴和 Y 轴。这些变换不涉及 Z 轴。3D 变换允许元素在三维空间中进行操作,这些…

大学英语ab级题搜题软件?分享7个支持答案和解析的工具 #笔记#其他

合理利用学习辅助工具和资料,可以帮助大学生更好地组织学习内容、掌握知识点和提升学术水平。 1.智能翻译官 这是一款多语言在线翻译神器,除了最基础的英语以外,还支持日语、德语、俄语、法语等几十种语言文本翻译和拍照翻译,并…

php代码执行计划任务dos实现方式和宝塔面板实现方式

dos php 计划任务 echo off :loop echo 这是一个死循环 echo This is an infinite loop. php think gpt php think ai timeout /t 2 goto loop 宝塔面板 php 计划任务 #!/bin/bash PATH/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH ste…

关于Ansible模块 ⑤

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

如何利用Flutter将应用成功上架至iOS平台:详细指南

引言 🚀 Flutter作为一种跨平台的移动应用程序开发框架,为开发者提供了便利,使他们能够通过单一的代码库构建出高性能、高保真度的应用程序,同时支持Android和iOS两个平台。然而,完成Flutter应用程序的开发只是第一步…

医院要不要安装医疗设备漏费控费管理系统

19339904493(康溪) 不知道大家有没有去医院做过检查,比如说做B超、彩超、多普勒、胃肠镜、心电、脑电,核磁、CT、DR、X光、钼靶、生化分析仪、血球等。你们可能不知道,在做检查、检验的时候还会存在一个漏洞。医院的存…

HarmonyOS NEXT应用开发之@Link装饰器:父子双向同步

子组件中被Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。 说明: 从API version 9开始,该装饰器支持在ArkTS卡片中使用。 概述 Link装饰的变量与其父组件中的数据源共享相同的值。 限制条件 Link装饰器不能在Entry装饰的自定义组件中使用…

Java常用API_时间

一,JDK7时间: 1.Date: 我先通过一段代码简单展示一下它的几个方法及功能 代码: 这里要注意的是 时间原点:1970年1月1日 00:00:00 中国的时间原点:由于中国处在东八区,时间原点要晚上8小时&…

MySQL 主从 AUTO_INCREMENT 不一致问题分析

本文介绍了 MySQL5.7 中常见的replace into 操作造成的主从auto_increment不一致现象,一旦触发了主从切换,业务的正常插入操作会触发主键冲突的报错提示。 一、问题描述 1.1 问题现象 在 MySQL 5.7 版本中,REPLACE INTO 操作在表存在自增主键…

nssm 工具把asp.net core mvc变成 windows服务,使用nginx反向代理访问

nssm工具的作用&#xff1a;把项目部署成Windows服务&#xff0c;可以在系统后台运行 1.创建一个asp.net core mvc的项目weblication1 asp.net core mvc项目要成为windows服务需要安装下面的nuget包 <ItemGroup><PackageReference Include"Microsoft.Extension…

2_7.Linux中的无人值守安装脚本kickstart

## 一.kickstart自动安装脚本的作用 ## #在企业中安装多台操作系统时面临的问题# 当安装Linux操作系统时&#xff0c;安装过程会需要回答很多关于设定的问题 这些问题必须手动选择&#xff0c;否则无法进行安装 当只安装1台Linux系统&#xff0c;手动选择设定工作量比较轻松 当…

『VUE』14. Style绑定(详细图文注释)

目录 行内css动态样式对象引入数组引入代码演示总结 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 大体上和前面的class绑定是一致的,只是class换成了style. 请注意,实际开发中,我们一般建议用class,因为style的权重太高了,用sty…

边缘计算采集网关如何助力制造企业解决数采问题-天拓四方

一、企业背景 某大型制造企业&#xff0c;位于国内某经济发达的工业园区内&#xff0c;拥有多个生产线和智能化设备&#xff0c;致力于提高生产效率、降低运营成本。随着企业规模的扩大和生产自动化的推进&#xff0c;该企业面临着海量数据处理、实时响应和网络安全等多重挑战…

ElementUI使用问题记录:设置路由+iconfont图标+自定义表单验证

一、关于导航怎么设置路由 1、在el-menu这个标签的属性中添加 router ,官方文档的解释是&#xff1a;启用vue-router 这种模式 2、在el-menu-item标签中的index属性直接书写路由&#xff0c;就可以实现正常vue-router了 3、在el-menu-item标签中书写路由属性&#xff1a;:route…

【C++进阶】哈希的应用之位图和布隆过滤器

位图和布隆过滤器 一&#xff0c;位图1. 实现2. 位图的应用 二&#xff0c;布隆过滤器1. 使用场景2. 模拟实现 三&#xff0c;海量数据面试题哈希切分 四&#xff0c;总结 这一节我们来看哈希的应用 一&#xff0c;位图 先来看一个面试题 这里如果用unordered_set来解决&…

C++11可变模板参数:海纳百川的Args

目录 一、可变模板参数的概念及功能 1.1Args的概念与使用 1.2获取args中的参数 二、emplace可变模板参数的实际应用 三、逗号表达式展开参数包 一、可变模板参数的概念及功能 1.1Args的概念与使用 C11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板…

二维码门楼牌管理应用平台建设:物业缴费的数字化革新

文章目录 前言一、物业缴费的数字化革新二、在线缴费功能的实现三、智能化缴费管理的优势四、面临的挑战与未来展望五、结语 前言 随着科技的不断进步&#xff0c;二维码门楼牌管理应用平台已成为物业管理的新趋势。在这样一个平台上&#xff0c;物业缴费的数字化革新不仅提高…

【计算机网络】TCP协议可靠传输保证(序列号/确认应答机制、超时重传、最长消息长度、滑动窗口控制、拥塞控制)

TCP协议可靠传输 1.序列号确认应答机制2.超时重传3.最长消息长度4.滑动窗口控制5.拥塞控制 1.序列号确认应答机制 这个机制类似于问答的形式。比如在课堂上老师会问你“明白了吗&#xff1f;”&#xff0c;假如你没有隔一段时间没有回应或者你说不明白&#xff0c;那么老师就会…