Vue3+Ts+Vite开发插件并发布到npm
依赖版本信息如下:
"vue": "^3.2.45""typescript": "~4.7.4""vite": "^4.0.0""less": "^4.1.3""terser": "^5.16.4"npm: 8.1.0node: 16.13.0
目标:创建 vue-amazing-ui 组件库,并发布到npm,效果如下图:
目前拥有的组件(面包屑和分页器):

①创建vue3+ts+vite项目:
npm init vue@latest(输入项目名称,并依次选择需要安装的依赖项)
②项目目录结构截图如下:

③在项目根目录新建 packages/ 文件夹用于存放组件

④在项目根目录中的 vite.config.ts 中写入相关配置项:
import { fileURLToPath, URL } from 'node:url'import { resolve } from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'// https://vitejs.dev/config/
export default defineConfig({plugins: [vue()],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}},css: {preprocessorOptions: {less: {modifyVars: { // 或者globalVars// `themeColor` is global variables fields namethemeColor: '#1890FF'},javascriptEnabled: true},},},// 配置打包入口build: {lib: { // 构建为库。如果指定了 build.lib,build.cssCodeSplit 会默认为 false。// __dirname的值是vite.config.ts文件所在目录entry: resolve(__dirname, 'packages/index.ts'), // entry是必需的,因为库不能使用HTML作为入口。name: 'VueAmazingUI', // 暴露的全局变量fileName: 'vue-amazing-ui' // 输出的包文件名,默认是package.json的name选项},rollupOptions: { // 自定义底层的Rollup打包配置// https://rollupjs.org/configuration-options/// 确保外部化处理那些你不想打包进库的依赖external: ['vue'],output: {exports: 'named',// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量globals: {vue: 'Vue'}}},/** 设置为 false 可以禁用最小化混淆,或是用来指定使用哪种混淆器。默认为 Esbuild,它比 terser 快 20-40 倍,压缩率只差 1%-2%。注意,在 lib 模式下使用 'es' 时,build.minify 选项不会缩减空格,因为会移除掉 pure 标注,导致破坏 tree-shaking。当设置为 'terser' 时必须先安装 Terser。(yarn add terser -D)*/minify: 'terser', // Vite 2.6.x 以上需要配置 minify: "terser", terserOptions 才能生效terserOptions: { // 在打包代码时移除 console.log、debugger 和 注释compress: { drop_console: false,drop_debugger: true,pure_funcs: ['console.log']},format: {comments: false // 删除注释}}}
})
⑤在 packages/ 文件夹下创建UI组件,例如:新建 breadcrumb/ 和 pagination/ 文件夹,截图如下:

⑥在 breadcrumb/ 文件夹下新建 Breadcrumb.vue 组件文件和 index.ts 文件,截图如下:

⑦在Breadcrumb.vue 中编写组件代码:
<script lang="ts">
export default { // 导出组件namename: 'Breadcrumb'
}
</script>
<script setup lang="ts">
import { computed } from 'vue'
import { useRouter } from 'vue-router'
export interface Props {routes: object[], // router的路由数组,没有 ? 时,即表示 required: trueheight?: number, // 面包屑高度separator?: string // 自定义分隔符
}
interface Route {path: string,query: object,name: string
}
const props = withDefaults(defineProps<Props>(), {routes: () => [],height: 60,separator: ''
})const len = computed(() => {return props.routes.length
})const router = useRouter()
function goRouter (route: Route):void {// @ts-ignore (忽略下一行中产生的错误)router.push({ path: route.path, query: route.query || {} })
}
</script>
<template><div class="m-breadcrumb" :style="`height: ${height}px;`"><div class="m-bread" v-for="(route, index) in routes" :key="index"><a:class="['u-route',{ active: index===len-1 }]"@click="index === len - 1 ? ($event:any) => $event.preventDefault() : goRouter(route)":title="route.name">{{ route.name || '--' }}</a><template v-if="index !== len - 1"><span v-if="separator" class="u-separator">{{ separator }}</span><svg v-else class="u-arrow" viewBox="64 64 896 896" data-icon="right" aria-hidden="true" focusable="false"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg></template></div><div class="assist"></div></div>
</template>
<style lang="less" scoped>
.m-breadcrumb {.m-bread {display: inline-block;vertical-align: middle;.u-route {height: 22px;font-size: 16px;font-weight: 400;line-height: 22px;color: #333;display: inline-block;vertical-align: middle;max-width: 240px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;cursor: pointer;&:hover {color: @themeColor;}}.active {color: @themeColor;cursor: default;}.u-separator {display: inline-block;vertical-align: middle;margin: 0 6px;}.u-arrow {.u-separator();margin: 0 5px;width: 12px;height: 12px;}}.assist {height: 100%;width: 0;display: inline-block;vertical-align: middle;}
}
</style>
⑧在 breadcrumb/index.ts 中导出组件
import type { App } from 'vue'
import Breadcrumb from './Breadcrumb.vue'// 使用install方法,在app.use挂载
Breadcrumb.install = (app: App) => {app.component(Breadcrumb.name, Breadcrumb)
}export default Breadcrumb
⑨在 packages/index.ts 文件中对整个组件库进行导出:
import type { App } from 'vue'
import Pagination from './pagination'
import Breadcrumb from './breadcrumb'// 所有组件列表
const components = [Pagination,Breadcrumb
]// 定义 install 方法
const install = (app: App): void => {// 遍历注册所有组件components.forEach(component => app.component(component.name, component))
}const VueAmazingUI = {install
}export { // 方便按需导入Pagination,Breadcrumb
}export default VueAmazingUI
⑩在 src/main.ts 中导入刚创建的组件,检测是否正常可用
import { Pagination, Breadcrumb } from '../packages/index'
// import { Pagination, Breadcrumb } from '../dist/vue-amazing-ui.js'
// import '../dist/style.css'
const app = createApp(App)
app.use(Pagination).use(Breadcrumb)app.mount('#app')
⑪在终端执行 npm init 初始化包,选填并配置package.json:
{"name": "vue-amazing-ui","version": "0.0.0","private": false,"type": "module","files": ["dist"],"main": "./dist/vue-amazing-ui.umd.cjs","module": "./dist/vue-amazing-ui.js","exports": {".": {"import": "./dist/vue-amazing-ui.js","require": "./dist/vue-amazing-ui.umd.cjs"}},"scripts": {"dev": "vite --port 9000 --open --force","build": "run-p type-check build-only","preview": "vite preview","build-only": "vite build --watch","type-check": "vue-tsc --noEmit","lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"},"dependencies": {"vue": "^3.2.45"},"devDependencies": {"@rushstack/eslint-patch": "^1.1.4","@types/node": "^18.11.12","@vitejs/plugin-vue": "^4.0.0","@vue/eslint-config-typescript": "^11.0.0","@vue/tsconfig": "^0.1.3","eslint": "^8.22.0","eslint-plugin-vue": "^9.3.0","less": "^4.1.3","npm-run-all": "^4.1.5","terser": "^5.16.4","typescript": "~4.7.4","vite": "^4.0.0","vue-tsc": "^1.0.12"},"description": "This template should help get you started developing with Vue 3 in Vite.","repository": {"type": "git","url": "git+https://github.com/themusecatcher/vue-amazing-ui.git"},"keywords": ["Vue3","TS","Vite","UI","components"],"author": "theMuseCatcher","license": "ISC","bugs": {"url": "https://github.com/themusecatcher/vue-amazing-ui/issues"},"homepage": "https://github.com/themusecatcher/vue-amazing-ui#readme"
}
name: 包名,该名字是唯一的。可在 npm 官网搜索名字,不可重复。
version: 版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同。
private:是否私有,需要修改为 false 才能发布到 npm
description: 关于包的描述。
main: 入口文件,需指向最终编译后的包文件。
keywords:关键字,以空格分离希望用户最终搜索的词。
author:作者
license: 开源协议
type: module:如果 package.json 不包含 "type": "module",Vite 会生成不同的文件后缀名以兼容 Node.js。.js 会变为 .mjs 而 .cjs 会变为 .js
files: ["dist/*"]:检测dist打包目录的所有文件
vite build --watch:当启用 --watch 标志时(启用 rollup 的监听器),对 vite.config.ts 的改动,以及任何要打包的文件,都将触发重新构建
vite --port 9000 --open --force:指定端口9000,启动时打开浏览器,强制优化器忽略缓存并重新构建。
⑫执行编译命令
yarn build(或num run build)
执行结果如下图:

⑬在项目根目录创建 .npmignore 文件,设置忽略发布的文件,类似 .gitignore 文件
只有编译后的 dist 目录、package.json、README.md是需要被发布的
# 忽略目录
.DS_Store
.vscode/
node_modules
packages/
public/
src/# 忽略指定文件
.eslintrc.cjs
.gitignore
.nomignore
.env.d.ts
index.html
tsconfig.config.json
tsconfig.json
vite.config.ts
yarn.lock
⑭编写README.md文件(使用markdown格式)
参考文档: http://markdown.p2hp.com/index.html
# vue-amazing-ui## 安装插件```
npm install vue-amazing-ui
或:yarn add vue-amazing-ui
```## 引入并注册插件```
import VueAmazingUI from 'vue-amazing-ui'
import '../node_modules/vue-amazing-ui/dist/style.css'app.use(VueUi)// 或者
import { Pagination, Breadcrumb } from 'vue-amazing-ui'
import '../node_modules/vue-amazing-ui/dist/style.css'app.use(Pagination).use(Breadcrumb)
```## 在项目中使用(示例)```
<Breadcrumb :routes="routes" :height="60" />
```
⑮登录npm
如果没有npm账号,可以去npm官网( npm) 注册一个账号
注册成功后在本地查看npm镜像:
npm config get registry
输出:http://registry.npmjs.org 即可
如果不是则需要设置为npm镜像:
npm config set registry https://registry.npmjs.org
然后在终端执行:
npm login
依次输入用户名,密码,邮箱
输出Logged in as…即可
npm whoami // 查看当前用户是否已登录
⑯发布组件到npm
在终端执行:npm publish
发布成功后即可在npm官网搜索到该组件,如下图;并可以通过 npm install vue-amazing-ui(或yarn add vue-amazing-ui)进行安装

⑰在要使用的项目中安装并注册插件:
yarn add vue-amazing-ui
然后在 main.ts 文件中引入并注册:
import VueAmazingUI from 'vue-amazing-ui'
// 或者 import { Pagination, Breadcrumb } from 'vue-amazing-ui'
import '../node_modules/vue-amazing-ui/dist/style.css'app.use(VueAmazingUI)
在要使用组件的页面直接使用即可:
<Breadcrumb :routes="routes" :height="60" />相关文章:
Vue3+Ts+Vite开发插件并发布到npm
依赖版本信息如下: "vue": "^3.2.45""typescript": "~4.7.4""vite": "^4.0.0""less": "^4.1.3""terser": "^5.16.4"npm: 8.1.0node: 16.13.0 目标…...
CAN TP层函数介绍
如果想使用CAN TP层函数,首先需要在网络节点或测试节点配置页面的Componets组件一栏添加osek_tp.dll文件。路径为:C:\Program Files\Vector CANoe 15\Exec32 至于节点的CAPL程序内需不需要引用这个dll文件,无所谓,可写可不写。但是如果是其他dll,必须在CAPL程序中引用。为…...
Spring架构篇--2.5 远程通信基础Select 源码篇--window--Select.open()
前言:在Socket通信中使用Select 来对NIO 进行实现,那么它们的实现方式是怎样的呢,本文从 Selector.open() 进行第一步的分析; Selector.open() : Selector 类: public static Selector open() throws IOEx…...
WEB静态交互展示【数据mock】
文章目录背景需求分析实现过程1.爬取原有项目数据2.将数据引入项目3.打包收工后记背景 接到公司一个【离谱】的需求,要求把已有的项目做一个演示版本(静态文件版本);本人觉得前端、后端搞个容器包,一个演示版本不就有…...
(4)C#传智:分支Switch与循环While(第四天)
一、异常捕获 定义:语法无错,程序因某些原因出现的错误,而不能正常运行。 用try-catch进行捕获。哪行代码可能出现异常,你就踹它一脚。 try { 可能会出现异常的代码; ---- …...
Stable-Baselines 3 部分源代码解读 2 on_policy_algorithm.py
Stable-Baselines 3 部分源代码解读 ./common/on_policy_algorithm.py 前言 阅读PPO相关的源码,了解一下标准库是如何建立PPO算法以及各种tricks的,以便于自己的复现。 在Pycharm里面一直跳转,可以看到PPO类是最终继承于基类,也…...
15. Qt中OPenGL的参数传递问题
1. 说明 在OPenGL中,需要使用GLSL语言来编写着色器的函数,在顶点着色器和片段着色器之间需要参数值的传递,且在CPU中的数据也需要传递到顶点着色器中进行使用。本文简单介绍几种参数传递的方式: (本文内容仅个人理解&…...
注意,这本2区SCI期刊最快18天录用,还差一步录用只因犯了这个错
发表案例分享: 2区医学综合类SCI,仅18天录用,录用后28天见刊 2023.02.10 | 见刊 2023.01.13 | Accepted 2023.01.11 | 提交返修稿 2022.12.26 | 提交论文至期刊部系统 录用截图来源:期刊部投稿系统 见刊截图来源:…...
Could not find resource jdbc.properties问题的解决
以如下开头的内容: Exception in thread "main" org.apache.ibatis.exceptions.PersistenceException: ### Error building SqlSession. ### The error may exist in SQL Mapper Configuration 出现以上问题是没有在src/main/resources下创建jdbc.prop…...
【面试题】==与equals区别、Hashcode作用、hashcode相同equals()也一定为true吗?泛型特点与好处
文章目录1. 和 equals 的区别是什么?2.Hashcode的作用3. 两个对象的hashCode() 相同, 那么equals()也一定为 true吗?4.泛型常用特点5.使用泛型的好处?1. 和 equals 的区别是什么? “” 对于基本类型和引用类型 的作…...
Flex布局中的flex属性
1.flex-grow,flex-shrink,flex-basis取值含义 flex-grow: 延申性描述。在满足“延申条件”时,flex容器中的项目会按照设置的flex-grow值的比例来延申,占满容器剩余空间。 取值情况: 取负值无效。取0值表示不…...
SpringBoot + Ant Design Pro Vue实现动态路由和菜单的前后端分离框架
Ant Design Pro Vue默认路由和菜单配置是采用中心化的方式,在 router.config.js统一配置和管理,同时也提供了动态获取路由和菜单的解决方案,并将在2.0.3版本中提供,因到目前为止,官方发布的版本为2.0.2,所以…...
robotframework自动化测试环境搭建
环境说明 win10 python版本:3.8.3rc1 安装清单 安装配置 selenium安装 首先检查pip命令是否安装: C:\Users\name>pipUsage:pip <command> [options]Commands:install Install packages.download Do…...
尚硅谷《Redis7》(小白篇)
尚硅谷《Redis7 》(小白篇) 02 redis 是什么 官方网站: https://redis.io/ 作者 Git Hub https://github.com/antirez 03 04 05 能做什么 06 去哪下 Download https://redis.io/download/ redis中文文档 https://www.redis.com.cn/docu…...
并非从0开始的c++ day6
并非从0开始的c day6二级指针练习-文件读写位运算位逻辑运算符按位取反 ~位于(AND):&位或(OR): |位异或: ^移位运算符左移<<右移>>多维数组一维数组数组名一维数组名传入到函数参数中数组指…...
PMP考前冲刺2.22 | 2023新征程,一举拿证
承载2023新一年的好运让我们迈向PMP终点一起冲刺!一起拿证!每日5道PMP习题助大家上岸PMP!!!题目1-2:1.在新产品开发过程中,项目经理关注到行业排名第一的公司刚刚发布同类型的产品。相比竞品&am…...
RxJava的订阅过程
要使用Rxjava首先要导入两个包,其中rxandroid是rxjava在android中的扩展 implementation io.reactivex:rxandroid:1.2.1implementation io.reactivex:rxjava:1.2.0首先从最基本的Observable的创建到订阅开始分析 Observable.create(new Observable.OnSubscribe<S…...
【2.22】MySQL、Redis、动态规划
认识Redis Redis是一种基于内存的数据库,对数据的读写操作都是在内存中完成的,因此读写速度非常快,常用于缓存,消息队列,分布式锁等场景。 Redis提供了多种数据类型来支持不同的业务场景,比如String(字符串…...
2年手动测试,裸辞后找不到工作怎么办?
我们可以从以下几个方面来具体分析下,想通了,理解透了,才能更好的利用资源提升自己。一、我会什么?先说第一个我会什么?第一反应:我只会功能测试,在之前的4年的中我只做了功能测试。内心存在一种…...
Leetcode6. N字形变换
一、题目描述: 将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 “PAYPALISHIRING” 行数为 3 时,排列如下: 之后,你的输出需要从左往右逐行读取,产…...
Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...
使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装
以下是基于 vant-ui(适配 Vue2 版本 )实现截图中照片上传预览、删除功能,并封装成可复用组件的完整代码,包含样式和逻辑实现,可直接在 Vue2 项目中使用: 1. 封装的图片上传组件 ImageUploader.vue <te…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
comfyui 工作流中 图生视频 如何增加视频的长度到5秒
comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗? 在ComfyUI中实现图生视频并延长到5秒,需要结合多个扩展和技巧。以下是完整解决方案: 核心工作流配置(24fps下5秒120帧) #mermaid-svg-yP…...
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...
shell脚本质数判断
shell脚本质数判断 shell输入一个正整数,判断是否为质数(素数)shell求1-100内的质数shell求给定数组输出其中的质数 shell输入一个正整数,判断是否为质数(素数) 思路: 1:1 2:1 2 3:1 2 3 4:1 2 3 4 5:1 2 3 4 5-------> 3:2 4:2 3 5:2 3…...
java 局域网 rtsp 取流 WebSocket 推送到前端显示 低延迟
众所周知 摄像头取流推流显示前端延迟大 传统方法是服务器取摄像头的rtsp流 然后客户端连服务器 中转多了,延迟一定不小。 假设相机没有专网 公网 1相机自带推流 直接推送到云服务器 然后客户端拉去 2相机只有rtsp ,边缘服务器拉流推送到云服务器 …...
Spring AI中使用ChatMemory实现会话记忆功能
文章目录 1、需求2、ChatMemory中消息的存储位置3、实现步骤1、引入依赖2、配置Spring AI3、配置chatmemory4、java层传递conversaionId 4、验证5、完整代码6、参考文档 1、需求 我们知道大型语言模型 (LLM) 是无状态的,这就意味着他们不会保…...
