Vite+Vue3 开发UI组件库并发布到npm

        一直对开源UI组件库比较感兴趣,摸索着开发了一套,虽然还只是开始,但是从搭建到发布这套流程基本弄明白了,现在分享给大家,希望对同样感兴趣的同学有所帮助。

        目前我的这套名为hasaki-ui的组件库仅有两个组件,大致成果如下,后续有时间会继续完善。

         该项目采用的技术栈为Vite + Vue3,还使用了一些基本的Markdown知识,阅读本文档前,希望你至少对vue有些基础,那么我们正式开始。

一、创建一个Vite项目

        参照vite官网,打开命令行,执行上述命令之一,按提示操作即可,创建完成后,你得到了一个以你创建的项目名为名的一个文件夹,我的为hasaki-ui,直接以成品进行说明吧。

二、组件开发 

         本文重点不在于某个组件的开发,而是库开发的配置、发布流程,所以在此以一个很简单的demo组件作为说明。

        doc.md为组件的说明文档,一般是用 Markdown 来写。这里我们需要使用 vite-plugin-vue-markdown插件来将 md 文件转换成 vue 文件。

// doc.md
<script setup>
import doc from './doc.vue';
import PreviewCode from '@/components/PreviewCode.vue'
</script># DEMO<doc/>
<PreviewCode compName="demo" />

doc.vue 为展示demo组件的vue文件

// doc.vue
<template><div class="demo-doc"><Demo /></div>
</template>
<script lang="ts">
export default {name: 'DemoDoc'
}
</script>
<script lang="ts" setup></script>
<style lang="scss" scoped>
.demo-doc {width: 100%;height: 100%;padding: 20px;
}
</style>

 库组件

// Demo.vue
<template><div class="demo">Demo is here</div>
</template>
<script lang="ts">
export default {name: 'Demo'
}
</script>
<script lang="ts" setup>
import { onMounted } from 'vue'onMounted(() => {console.log('demo 出现啦')
})
// endregion
</script>
<style lang="scss" scoped>
.demo {height: 100%;width: 100%;display: flex;flex-direction: column;overflow: hidden;
}
</style>

 PreviewCode.vue组件用于获取组件源码,用于在页面展示源码

// PreviewCode.vue
<template><div class="preview-code"><div class="showCode" @click="showOrhideCode"><span>{{ showCode ? '隐藏代码' : '显示代码' }} &lt; &gt;</span></div><el-scrollbar><transition><pre v-highlight v-if="showCode"><code>{{ sourceCode }}</code></pre></transition></el-scrollbar></div>
</template><script setup>
import { onMounted, ref } from 'vue'const props = defineProps({compName: {type: String,default: '',require: true}
})const showCode = ref(false)
const sourceCode = ref('')const showOrhideCode = () => {showCode.value = !showCode.value
}const getSourceCode = async () => {let code = await import(/* @vite-ignore */ `@/components/hasaki-ui/${props.compName}/doc/doc.vue?raw`)sourceCode.value = code.default
}onMounted(() => {getSourceCode()
})
</script>
<style lang="scss">
.preview-code {height: 300px;.showCode {cursor: pointer;color: #777;text-align: right;padding-right: 50px;&:hover {color: #409eff;}}
}.v-enter-active,
.v-leave-active {transition: all 0.5s ease;
}.v-enter-from,
.v-leave-to {opacity: 0;transform: translateY(200px);
}
</style>

 组件出口

// index.ts
import ElTablePagination from './ElTablePagination/ElTablePagination.vue'
import SelectTree from './SelectTree/SelectTree.vue'
import Demo from './demo/Demo.vue'// 按需引入
export { ElTablePagination, SelectTree, Demo }const component = [ElTablePagination, SelectTree, Demo]const HasakiUI = {install(App: any) {component.forEach((item) => {App.component(item.name, item)})}
}export default HasakiUI

在src的main.ts中引入组件库

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import HasakiUI from './components/hasaki-ui'import hljs from 'highlight.js' // 引入代码高亮文件
import 'highlight.js/styles/color-brewer.css'const app = createApp(App)app.directive('highlight', function (el) {const blocks = el.querySelectorAll('pre code')blocks.forEach((block) => {hljs.highlightBlock(block)})
})app.use(router)
app.use(HasakiUI)
app.mount('#app')

接下来我们简单写下项目外壳样式

// views/home-page.vue
<template><div class="home-page"><div class="home-page-sidebar"><div class="logo"><img src="/favicon.ico" alt="" />hasaki-ui</div><ul v-for="item in routes" :key="item"><liv-for="(ele, index) in item.children":key="ele":class="{ active: mIndex == index }"@click="goPath(ele, index)">{{ ele.name }}</li></ul></div><main class="home-page-main"><router-view></router-view></main></div>
</template><script setup>
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'const router = useRouter()
const mIndex = ref(sessionStorage.getItem('mIndex') || '0')
const routes = computed(() => router.options.routes)const goPath = (ele, index) => {mIndex.value = indexrouter.push({path: ele.path})sessionStorage.setItem('mIndex', index)
}
</script><style lang="scss" scoped>
.home-page {display: flex;justify-content: space-between;width: 100%;height: 100%;overflow: hidden;&-sidebar {width: 200px;height: 100%;border-right: 1px solid #eee;text-align: center;.logo {display: flex;align-items: center;padding: 15px;font-size: 20px;img {width: 25px;margin-right: 10px;}}ul {li {height: 50px;line-height: 50px;cursor: pointer;}.active {color: #409eff;background-color: #ecf5ff;border-right: 1px solid #409eff;}}}&-main {flex: 1;padding: 20px 50px;overflow-y: auto;}
}
</style>

配置路由

// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
const routes = [{path: '/',name: '组件页面',component: () => import('@/views/home-page.vue'),redirect: '/demo',children: [{path: '/demo',name: 'Demo',// @ts-ignorecomponent: () => import('@/components/hasaki-ui/demo/doc/doc.md')},{path: '/el-table-pagination',name: '分页表格',// @ts-ignorecomponent: () => import('@/components/hasaki-ui/ElTablePagination/doc/doc.md')},{path: '/select-tree',name: '树选择器',// @ts-ignorecomponent: () => import('@/components/hasaki-ui/SelectTree/doc/doc.md')}]}
]
const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes
})export default router
// App.vue
<script setup lang="ts"></script>
<template><div class="main"><RouterView /></div>
</template>
<style scoped lang="scss">
.main {width: 100vw;height: 100vh;
}
</style>

Markdown 插件需要我们在vite.config.ts中进行配置

到这里我们的一个简单的组件库demo就完成了

三、库模式开发打包配置 

        在此我们介绍如何把我们开发的组件库进行打包,重点是配置lib字段来进行库开发

// vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import Markdown from 'vite-plugin-vue-markdown'// https://vitejs.dev/config/
export default defineConfig({base: '/hasaki-ui/',plugins: [vue({include: [/\.vue$/, /\.md$/]}),vueJsx(),Markdown()],build: {outDir: 'hasaki-ui', //输出文件名称lib: {entry: fileURLToPath(new URL('./src/components/hasaki-ui/index.ts', import.meta.url)), //指定组件编译入口文件name: 'hasaki-ui', // 包名fileName: 'hasaki-ui' // 打包文件名}, //库编译模式配置rollupOptions: {// 确保外部化处理那些你不想打包进库的依赖external: ['vue', 'vue-router'],output: {// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量globals: {vue: 'Vue'}}}, // rollup打包配置terserOptions: {// 在打包代码时移除 console、debugger 和 注释compress: {/* (default: false) -- Pass true to discard calls to console.* functions.If you wish to drop a specific function call such as console.info and/orretain side effects from function arguments after dropping the functioncall then use pure_funcs instead*/drop_console: true, // 生产环境时移除consoledrop_debugger: true // 生产环境时移除debugger},format: {comments: false // 删除注释comments}}},resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url))}}
})

在package.json中配置发布信息

{"name": "hasaki-ui", // 发布包的名称"version": "0.0.5",  // 版本号,每次更新注意升级版本号"private": false, // 是否为私有,这里注意应为false"main": "./hasaki-ui/hasaki-ui.umd.js", // 入口文件"module": "./hasaki-ui/hasaki-ui.mjs", // 模块入口"sideEffects": false,"keywords": ["hasaki","hasaki-ui","HasakiUI"], // 搜索关键词"description": "一款基于Element-Plus开发的UI组件库,适用于vue3,大多为PC端后台管理系统常用组件", // 描述"author": "YXX", // 作者"exports": {"./hasaki-ui/style.css": "./hasaki-ui/style.css",".": {"import": "./hasaki-ui/hasaki-ui.mjs","require": "./hasaki-ui/hasaki-ui.umd.js"}}, // 引用路径映射,解决加载样式失败问题"files": ["hasaki-ui/*"], // 描述了将软件包作为依赖项安装时要包括的条目,默认值为[“*”],这意味着它将包括所有文件,我们指定我们自己组件文件夹即可// ..重要的就上面这些
}

执行 npm/yarn/pnpm run build进行打包,出现如下表示打包成功了

四、发布

这一步其实很简单,一个命令搞定,npm publish,但是初次发布需要登录你的npm:

1、执行npm login 命令,输入用户名和密码,输入密码时是看不到的,之后按提示输入绑定的邮箱,成功后你的邮箱会收到一个one-time password,填入后即登录成功。

2、登录之后,就可以执行npm publish进行发布。

3、发布前要注意查看你的npm源是否为官方源https://registry.npmjs.org ,如果不是要切回官方源,否则发布失败

4、发布成功后,到npm上就可以看到我们的包了,至此我们就有了自己的一个开源包。

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

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

相关文章

分布式异步任务处理组件(五)

节点上线和下线的逻辑-- 节点下线分为两种--心跳失败主动或被动和主节点断开连接&#xff0c;但是节点本身没有发生重启&#xff1b;第二种就是节点宕机重启--其实这两中情况下处理逻辑都是一样的&#xff0c;只是节点本身如果还能消费到kafka的时候可以继续执行任务但是不能从…

分布式异步任务处理组件(四)

基于zookeeper的HA集群设计思路-- 各个节点都可以消费任务&#xff0c;但是由主节点来投票&#xff1b;主节点通过注册zookeeper的临时节点来选举--主节点需要同步从节点的信息正常工作机制--各个节点&#xff08;包括主节点本身&#xff09;在执行任务之前询问主节点&#xf…

IntelliJ IDEA 2023.2 最新变化

主要更新 AI Assistant 限定访问 Ultimate 在此版本中&#xff0c;我们为 IntelliJ IDEA 引入了一项重要补充 – AI Assistant。 AI Assistant 当前具备一组由 AI 提供支持的初始功能&#xff0c;提供集成式 AI 聊天&#xff0c;可以完成一些任务&#xff0c;例如自动编写文档…

【计算机视觉】BLIP:统一理解和生成的自举多模态模型

文章目录 一、导读二、背景和动机三、方法3.1 模型架构3.2 预训练目标3.3 BLIP 高效率利用噪声网络数据的方法&#xff1a;CapFilt 四、实验4.1 实验结果4.2 各个下游任务 BLIP 与其他 VLP 模型的对比 一、导读 BLIP 是一种多模态 Transformer 模型&#xff0c;主要针对以往的…

5、Kubernetes核心技术 - Controller控制器工作负载

目录 一、Deployments - 控制器应用 二、Deployment升级回滚和弹性收缩 2.1、创建一个 1.14 版本的 pod 2.2、应用升级 2.3、查看升级状态 2.4、查看历史版本 2.5、应用回滚 2.6、弹性伸缩 三、StatefulSet - 有状态应用 四、DaemonSet - 守护进程 五、Job - 单次任…

Linux近两年高危漏洞修复过程记录

一、背景 2023年8月份&#xff0c;面对即将到来的“大运会”、“亚运会”&#xff0c;今年的例行安全护网阶段也将迎来新的挑战和时刻&#xff0c;为此相关部门发布了国家级实战攻防演练已进入紧急「备战」时刻&#xff01;这里我们主要说一下Linux OS层面的漏洞处理&#xff0…

spring5源码篇(12)——spring-mvc请求流程

spring-framework 版本&#xff1a;v5.3.19 文章目录 一、请求流程1、处理器映射器1.1、 RequestMappingHandlerMapping1.2、获取对应的映射方法1.3、添加拦截器 2、获取合适的处理器适配器3、通过处理器适配器执行处理器方法3.1、拦截器的前置后置3.2、处理器的执行3.2.1 参数…

React哲学——官方示例

在本篇技术博客中&#xff0c;我们将介绍React官方示例&#xff1a;React哲学。我们将深入探讨这个示例中使用的组件化、状态管理和数据流等核心概念。让我们一起开始吧&#xff01; 项目概览 React是一个流行的JavaScript库&#xff0c;用于构建用户界面。React的设计理念是…

QuantMania!《快乐机器学习》和《Python 从入门到入迷》作者,FRM,CAIA

王的机器主理人 王圣元 (FRM, CAIA) 某加密货币公司 Head of Quant 冬海集团 SeaMoney 建模负责人 八方咨询 量化总监 新加坡国立大学金融数学硕士 新加坡国立大学量化金融学士 《快乐机器学习》的作者 《Python 从入门到入迷》的作者 第一本书 《快乐机器学习》 第二本书《Pyt…

【图论】BFS中的最短路模型

算法提高课笔记 目录 单源最短路迷宫问题题意思路代码 武士风度的牛题意思路代码 抓住那头牛题意思路代码 多源最短路矩阵距离题意思路代码 双端队列BFS电路维修题意思路代码&#xff08;加了注释&#xff09; BFS可以解决边权为1的最短路问题&#xff0c;下面是相关例题 单源…

解决ComposerStaticInit类重复加载问题

Tp5中composer安装phpoffice后报错 Cannot declare class Composer\Autoload\ComposerStaticInit6c9266e89aa536667bf36f59ad8e6e6b, because the name is already in use 错误原因: 使用ThinkPHP5框架的项目&#xff0c;在引用某些包的时候&#xff0c;可能会通过其它包&…

位图和 DC 有什么特别之处?

相信设备上下文 (DC, Device Context) 对你来说&#xff0c;应该很熟悉。 基本工作方式是&#xff0c;你可以通过调用 SelectObject 来将画笔(Pen)&#xff0c;画刷(Brush)&#xff0c;字体(Font)和位图(Bitmap)等这些对象选入设备上下文中&#xff0c;但是&#xff0c;这里的位…

初学HTML:采用CSS绘制一幅夏天的图

下面代码使用了HTML和CSS来绘制一幅炎炎夏日吃西瓜的画面。其中&#xff0c;使用了伪元素和阴影等技巧来实现部分效果。 <!DOCTYPE html> <html> <head><title>炎炎夏日吃西瓜</title><style>body {background-color: #add8e6; /* 背景颜…

小程序原生实现左右锚点联动

效果 wxml <view classbox><scroll-view scroll-y scroll-with-animation style"width:25%"><view classnav><view wx:for"{{navList}}" wx:keyindex class"title {{index active ?select:}}"data-index{{index}} bin…

Windows下安装Hive(包安装成功)

Windows下安装Hive Hive与Hadoop的版本选择很关键&#xff0c;千万不能选错&#xff0c;否则各种报错。一、Hive下载1.1、官网下载Hive1.2、网盘下载Hive 二、解压安装包&#xff0c;配置Hive环境变量2.1、环境变量新增&#xff1a;HIVE_HOME2.2、修改Path环境变量&#xff0c;…

JVM、Redis、反射

JVM JVM是Java virtual machine&#xff08;Java虚拟机&#xff09;的缩写&#xff0c;是一种用于计算机的规范&#xff0c;是通过在实际计算机上仿真模拟各种计算机功能来实现的。 主要组件构成&#xff1a; 1.类加载器 子系统负责从文件系统或者网络中加载Class文件&…

深度学习实战 | 开发一个围棋智能体

01、数据模型 神经网络的训练过程需要将HD5文件中的样本数据解析出来。数据集中的棋盘局面可以提取后直接输入卷积网络进行特征提取。从属性中取出样本标签用于神经网络的损失计算和反向传播。如图1所示&#xff0c;落子方信息从属性中提取后不用参与棋盘局面的特征提取&#…

Spire.Office for.NET Crack

Spire.Office for.NET Crack Spire.Office for.NET是E-iceblue提供的企业级Office.NET API的组合。它包括Spire.Doc、Spire.XLS、Spire.Seadsheet、Spire.Presentation、Spire_PDF、Spire.DataExport、SpireOfficeViewer、Spire-PDFViewer、Spire.DocViewer、Spire.Barcode和Sp…

在linux中怎样同时运行三个微服务保证退出时不会终止

前言 1.maven中打jar包 使用插件打包,必须在pom.xml中添加插件,否则不能在linux中编译运行 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version&g…

AMEYA详解松下Panasonic HF SSOP 1 Form A AQY PhotoMOS继电器

Panasonic HF SSOP 1 Form A AQY PhotoMOS继电器采用微型SSOP封装&#xff0c;具有600V的负载电压和1500Vrms 的I/O隔离电压 这些继电器具有8Ω的低导通电阻和高速运行的特点&#xff0c;SSOP封装旨在实现高密度安装。Panasonic HF SSOP AQY PhotoMOS继电器适用于从测试和测量设…