likes
comments
collection
share

vite 发布基于 Ant Design Vue 二次封装的组件库到 npm

作者站长头像
站长
· 阅读数 20

之前对 Ant Design TreeSelect 组件进行了二次封装,可查看文章Antd TreeSelect 树选择控件“二次封装”及封装原理,现在使用 vite 将该组件发布到 npm 上,整体打包发布流程和使用 vite 发布自定义组件到 npm基本一致,如下只列出差异部分

Ant Design Vue 组件库按需引入

  1. 安装依赖
pnpm i ant-design-vue
pnpm i vite-plugin-components -D
  1. 按需配置
// 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树选择组件的二次封装,这个比较简陋,只是做为测试发布使用

  1. 新建 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>
  1. 新建 packages/treeSelect/index.js 文件
import tTreeSelect from "./src/index.vue";

tTreeSelect.install = function (Vue) {
  Vue.component(tTreeSelect.name, tTreeSelect);
};

export default tTreeSelect;

打包配置

  1. 修改 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",
        },
      },
    },
  },
});
  1. 修改 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>

代码展示:

vite 发布基于 Ant Design Vue 二次封装的组件库到 npm

使用效果展示:

vite 发布基于 Ant Design Vue 二次封装的组件库到 npm

自定义组件库发布

自定义组件库实现发布,主要是以之前的两个组件 tButton 和 tTreeSelect为例,当然你也可以发布更多

  1. 在 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,
};
  1. 修改 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",
        },
      },
    },
  },
});
  1. 修改 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"
  }
}
  1. 打包发布
// 打包
pnpm build

// 发布
npm publish
  1. 使用测试:发布成功后,在本地下载测试
<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>