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 时,排列如下: 之后,你的输出需要从左往右逐行读取,产…...
别再手动下载模型了!用Xinference一键部署Qwen、ChatGLM等大模型(附CUDA环境配置避坑指南)
别再手动下载模型了!用Xinference一键部署Qwen、ChatGLM等大模型(附CUDA环境配置避坑指南) 在AI模型部署的实践中,手动下载模型文件、配置复杂环境、解决依赖冲突等问题常常让开发者头疼不已。传统部署流程不仅耗时耗力࿰…...
Minimum Snap轨迹优化:从理论到实践的无人机巡检路径规划
1. 为什么无人机巡检需要Minimum Snap算法 去年给某电力公司做巡检方案时,他们的老飞手给我看了一段视频:无人机在高压线塔间穿行时,摄像头画面抖动得像在跳机械舞,关键部位的图像全是模糊的残影。这正是传统航点飞行模式的典型痛…...
5分钟搞定OpenClaw飞书接入:Qwen3.5-9B对话机器人配置
5分钟搞定OpenClaw飞书接入:Qwen3.5-9B对话机器人配置 1. 为什么选择OpenClaw飞书Qwen3.5-9B组合 上周我在整理团队周报时,突然意识到一个痛点:每次都要反复切换浏览器、文档和聊天工具,手动复制粘贴信息。这种机械操作不仅浪费…...
Open Interpreter一文详解:从安装到GUI控制完整步骤
Open Interpreter一文详解:从安装到GUI控制完整步骤 1. 引言:你的本地AI编程助手 想象一下,你对着电脑说:“帮我分析一下这个月的销售数据,做个趋势图”,然后AI就开始自动写Python代码、读取你的Excel文件…...
TranslucentTB:Windows任务栏透明化工具,让桌面视觉体验焕然一新
TranslucentTB:Windows任务栏透明化工具,让桌面视觉体验焕然一新 【免费下载链接】TranslucentTB A lightweight utility that makes the Windows taskbar translucent/transparent. 项目地址: https://gitcode.com/gh_mirrors/tr/TranslucentTB …...
【华为OD机试真题】战场索敌 · 区域统计问题 (Java/Go)
一、题目题目描述:有一个大小是 N*M 的战场地图,被墙壁 # 分隔成大小不同的区域。上下左右四个方向相邻的空地 . 属于同一个区域。只有空地上可能存在敌人 E。请求出地图上总共有多少区域里的敌人数小于 K。输入描述:第一行输入为 N, M, K&am…...
7.企业级开发
一.软件开发的流程二.系统开发环境三.分支设计规范Git Flow模型四.企业级项目管理https://gitee.com/enterprises1.创建项目2.创建项目对应的仓库3.添加成员还可以进行(项目/仓库)成员管理五.开发实战场景1.创建仓库时,一般选生产和开发模型,其他的分支自己创建2.创建新分支:3.…...
VMware安装RHEL9连接Xshell与Linux基础命令vim练习
1、在VMware上创建虚拟机以及安装RHEL9操作系统,使用ssh进行远程连接2、文件管理命令练习: 1(1)在/opt目录下创建一个临时目录tmp;2(2)在临时目录下创建一个文件,文件名为a.txt;3、vi/vim练习:完成如下步骤(1)应用vi命令在/tmp文件夹下创建文…...
飞书文档全流程备份终极方案:从手动操作到自动化管理的完美转型
飞书文档全流程备份终极方案:从手动操作到自动化管理的完美转型 【免费下载链接】feishu-doc-export 项目地址: https://gitcode.com/gh_mirrors/fe/feishu-doc-export 价值定位:破解企业文档管理的三大核心痛点 📊 在数字化办公日益…...
Python张量框架选型不是技术问题,而是组织问题:CTO必须在立项前确认的5个战略问题(含人才储备周期、长期维护成本、专利风险审计清单)
第一章:Python张量框架选型不是技术问题,而是组织问题当团队在 PyTorch、TensorFlow 和 JAX 之间反复争论“哪个性能更好”或“哪个 API 更优雅”时,往往已陷入技术决定论的误区。真正制约张量框架落地效果的,是组织内部的协同惯性…...
