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 时,排列如下: 之后,你的输出需要从左往右逐行读取,产…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
