vite 发布基于 Ant Design Vue 二次封装的组件库到 npm
之前对 Ant Design TreeSelect 组件进行了二次封装,可查看文章Antd TreeSelect 树选择控件“二次封装”及封装原理,现在使用 vite 将该组件发布到 npm 上,整体打包发布流程和使用 vite 发布自定义组件到 npm基本一致,如下只列出差异部分
Ant Design Vue 组件库按需引入
- 安装依赖
pnpm i ant-design-vue
pnpm i vite-plugin-components -D
- 按需配置
// 2.1 新增src/libs/antdv.js
import { TreeSelect } from "ant-design-vue";
const components = [TreeSelect];
export function setupAntd(app) {
components.forEach((component) => {
app.use(component);
});
}
// 2.2 main.js引入
import { setupAntd } from "./libs/antdv";
const app = createApp(App);
setupAntd(app);
app.mount("#app");
// 2.3 vite.config.js配置
import ViteComponents, { AntDesignVueResolver } from "vite-plugin-components";
export default defineConfig({
plugins: [
vue(),
ViteComponents({
customComponentResolvers: [AntDesignVueResolver()],
}),
],
});
组件编写
完成treeSelect树选择组件的二次封装,这个比较简陋,只是做为测试发布使用
- 新建 packages/treeSelect/src/index.vue
<template>
<a-tree-select
v-bind="$attrs"
placeholder="请选择"
style="width: 100%"
:tree-data="departSource"
:dropdownStyle="{ maxHeight: '400px', overflow: 'auto' }"
show-search
allow-clear
tree-default-expand-all
treeNodeFilterProp="title"
:getPopupContainer="(triggerNode) => triggerNode.parentNode"
@select="handleSelect"
>
</a-tree-select>
</template>
<script>
import { watchEffect } from "vue";
export default {
name: "tTreeSelect",
props: {
// 数据源
departSource: {
type: Array,
default: [],
},
},
setup(props, context) {
console.log("props:", props);
console.log("context.attrs:", context.attrs); // $attrs
console.log("context.slots:", context.slots); // $slots
console.log("context.emit:", context.emit); // $slots
console.log("context.expose:", context.expose); // vue3.2 新增
watchEffect(() => {
console.log(`value is: ` + context.attrs.value);
});
const handleSelect = (value, node, extra) => {
console.log(value, node, extra);
};
return { handleSelect };
},
};
</script>
<style scoped></style>
- 新建 packages/treeSelect/index.js 文件
import tTreeSelect from "./src/index.vue";
tTreeSelect.install = function (Vue) {
Vue.component(tTreeSelect.name, tTreeSelect);
};
export default tTreeSelect;
打包配置
- 修改 vite.config.js 文件
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
// 安装插件
import ViteComponents, { AntDesignVueResolver } from "vite-plugin-components";
import path from "path";
const resolve = (dir) => path.join(__dirname, dir);
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
ViteComponents({
customComponentResolvers: [AntDesignVueResolver()],
}),
],
resolve: {
alias: {
"@": resolve("src"),
packages: resolve("packages"),
},
},
build: {
lib: {
// 2. 基于Ant Design Vue TreeSelect二次封装的组件的打包配置
entry: resolve("packages/treeSelect/index.js"),
name: "TTreeSelect",
fileName: (format) => `tTreeSelect.${format}.js`,
},
// 自定义构建配置,可直接调整底层Rollup选项;Rollup有一套预设
// https://rollupjs.org/guide/en/#big-list-of-options
rollupOptions: {
// 确保外部化处理那些你不想打包进库的依赖
external: ["vue"],
output: {
// 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
globals: {
vue: "Vue",
},
},
},
},
});
- 修改 package.json 文件
{
"name": "vite-npm-package",
"version": "2.0.0",
"description": "使用vite发布自定义组件到npm",
"files": ["dist"],
"main": "./dist/tTreeSelect.umd.js",
"module": "./dist/tTreeSelect.es.js",
"exports": {
".": {
"import": "./dist/tTreeSelect.es.js",
"require": "./dist/tTreeSelect.umd.js"
},
"./dist/style.css": {
"import": "./dist/style.css",
"require": "./dist/style.css"
}
},
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"license": "MIT",
"private": false,
"author": "zptime",
"dependencies": {
"ant-design-vue": "^3.0.0-alpha.14",
"vue": "^3.2.23"
},
"devDependencies": {
"@vitejs/plugin-vue": "^1.10.2",
"vite": "^2.7.0",
"vite-plugin-components": "^0.13.3"
}
}
使用举例
<template>
<div class="demo">
<t-tree-select
:depart-source="departTree"
v-model:value="departId"
:fieldNames="fieldNames"
/>
</div>
</template>
<script setup>
// 1. 本地引入
import tTreeSelect from "packages/treeSelect/src/index.vue";
// 2. 打包后引入(pnpm build)
import tTreeSelect from "../../dist/tTreeSelect.es.js";
import "../../dist/style.css";
// 3. 发包到npm后使用 v2.0.0
import tTreeSelect from "vite-npm-package";
import "vite-npm-package/dist/style.css";
const fieldNames = {
children: "children",
label: "name",
key: "id",
value: "id",
};
// 测试数据
const departTree = [
{
id: 1,
name: "根部门",
departNumber: 6,
children: [
{
id: 11,
pid: 1,
name: "一级部门1",
departNumber: 2,
children: [
{ id: 111, pid: 11, name: "二级部门1", departNumber: 0 },
{ id: 112, pid: 11, name: "二级部门2", departNumber: 0 },
],
},
{ id: 21, pid: 1, name: "一级部门2", departNumber: 0 },
{ id: 31, pid: 1, name: "一级部门3", departNumber: 0 },
{ id: 41, pid: 1, name: "一级部门4", departNumber: 0 },
{ id: 51, pid: 1, name: "一级部门5", departNumber: 0 },
{
id: 61,
pid: 1,
name: "一级部门6",
departNumber: 2,
children: [
{ id: 611, pid: 61, name: "二级部门3", departNumber: 0 },
{ id: 612, pid: 61, name: "二级部门4", departNumber: 0 },
],
},
],
},
];
const departId = 11;
</script>
<style scoped></style>
代码展示:
使用效果展示:
自定义组件库发布
自定义组件库实现发布,主要是以之前的两个组件 tButton 和 tTreeSelect为例,当然你也可以发布更多
- 在 package 文件夹下新增 index.js 文件,将自定义组件一起引入
import tButton from "./button";
import tTreeSelect from "./treeSelect";
const components = [tButton, tTreeSelect];
// 如果想通过CDN方式引入,需要编写install函数
// 注册组件
const install = function (Vue) {
components.forEach((component) => {
Vue.component(component.name, component);
});
};
if (typeof window !== "undefined" && window.Vue) {
install(window.Vue);
}
// 导出组件
export default {
install,
tButton,
tTreeSelect,
};
- 修改 vite.config.js 配置,处理 packages 的打包
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import ViteComponents, { AntDesignVueResolver } from "vite-plugin-components";
import path from "path";
const resolve = (dir) => path.join(__dirname, dir);
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
ViteComponents({
customComponentResolvers: [AntDesignVueResolver()],
}),
],
resolve: {
alias: {
"@": resolve("src"),
packages: resolve("packages"),
},
},
build: {
lib: {
// 3. 发布自定义组件库,包含tButton 和 tTreeSelect两个组件
entry: resolve("packages/index.js"),
name: "tAntDesign",
fileName: (format) => `tAntDesign.${format}.js`,
},
rollupOptions: {
external: ["vue"],
output: {
globals: {
vue: "Vue",
},
},
},
},
});
- 修改 package.json 文件,调整发布的相关信息
{
"name": "vite-npm-package",
"version": "3.0.0",
"description": "使用vite发布自定义组件库到npm",
"files": ["dist"],
"main": "./dist/tAntDesign.umd.js",
"module": "./dist/tAntDesign.es.js",
"exports": {
".": {
"import": "./dist/tAntDesign.es.js",
"require": "./dist/tAntDesign.umd.js"
},
"./dist/style.css": {
"import": "./dist/style.css",
"require": "./dist/style.css"
}
},
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"license": "MIT",
"private": false,
"author": "zptime",
"dependencies": {
"ant-design-vue": "^3.0.0-alpha.14",
"vite-npm-package": "^2.0.0",
"vue": "^3.2.23"
},
"devDependencies": {
"@vitejs/plugin-vue": "^1.10.2",
"vite": "^2.7.0",
"vite-plugin-components": "^0.13.3"
}
}
- 打包发布
// 打包
pnpm build
// 发布
npm publish
- 使用测试:发布成功后,在本地下载测试
<template>
<div class="demo">
本地引入
<t-button class="block" />
<t-tree-select
:depart-source="departTree"
v-model:value="departId"
:fieldNames="fieldNames"
/>
</div>
</template>
<script setup>
import tAntDesign from "vite-npm-package";
import "vite-npm-package/dist/style.css";
const { tButton, tTreeSelect } = tAntDesign;
</script>
转载自:https://juejin.cn/post/7156585981611606047