【vue组件库搭建06】组件库构建及npm发包

一、格式化目录结构

根据以下图片搭建组件库目录

index.js作为入口文件,将所有组件引入,并注册组件名称

import { EButton } from "./Button";
export * from "./Button";
import { ECard } from "./Card";
export * from "./Card";

const cmpts = [EButton, ECard];

const EricUI = {
  install(Vue) {
    cmpts.forEach(cmpt => {
      Vue.component(cmpt.name, cmpt);
    });
  },
};

export default EricUI;

utils.js:给组件绑定注册方法

export function withInstall(component) {
  component.install = app => {
    app.component(component.name, component);
  };
  return component;
}

在main.js中引入,方便后续使用

import { createApp } from "vue";
import "./style.css";
import App from "./App.vue";

import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.less";

import EricUI from "../components";

const app = createApp(App).use(Antd).use(EricUI).mount("#app");

在docs\.vitepress\theme\index.ts同样引入

// https://vitepress.dev/guide/custom-theme
import { h } from 'vue'
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'

import Antd from 'ant-design-vue';
import './antd-overwrite.less'

import { AntDesignContainer } from '@vitepress-demo-preview/component'
import '@vitepress-demo-preview/component/dist/style.css'

import './style.css'

import HomeImage from './HomeImage.vue'
import EricUI from "../../../components";

export default {
  extends: DefaultTheme,
  Layout: () => {
    return h(DefaultTheme.Layout, null, {
      // https://vitepress.dev/guide/extending-default-theme#layout-slots
      'home-hero-image': () => h(HomeImage)
    })
  },
  enhanceApp({ app, router, siteData }) {
    app.use(Antd)
    app.use(EricUI)
    app.component('demo-preview', AntDesignContainer)
  }
} satisfies Theme

到此为止,组件库开发的组件可以在docs中展示:

EButton是我们开发的button组件,在Button.md中引入

 效果:

二、组件库构建

 新建build文件夹,以及以下三个文件:

// base.confi.js

import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";

// 文档: https://vitejs.dev/config/
export default defineConfig({
  minify: false,
  css: {
    preprocessorOptions: {
      less: {
        javascriptEnabled: true,
        modifyVars: {
          "ant-prefix": "ant",
        },
      },
    },
  },
  plugins: [],
  resolve: {
    alias: {
      "@": fileURLToPath(new URL("../src", import.meta.url)),
    },
  },
});
// lib.config.js

import { defineConfig } from "vite";
import { fileURLToPath, URL } from "node:url";
import vue from "@vitejs/plugin-vue";
import lessEntry from "./vite-plugin-less-entry";
import baseConfig from "./base.config";
import vueJsx from "@vitejs/plugin-vue-jsx";
import { viteStaticCopy } from "vite-plugin-static-copy";

export default defineConfig({
  ...baseConfig,
  build: {
    sourcemap: true,
    outDir: "lib",
    lib: {
      entry: fileURLToPath(new URL("../components/index.js", import.meta.url)),
      name: "EricUI",
      fileName: format => `eric-ui.${format}.js`,
    },
    rollupOptions: {
      // 确保外部化处理那些你不想打包进库的依赖
      external: [
        "vue",
        "@ant-design/icons-vue",
        "vxe-table",
        "xe-utils",
        "@vitepress-demo-preview/component",
        "@vitepress-demo-preview/plugin",
      ],
    },
  },
  plugins: [
    vue(),
    vueJsx(),
    viteStaticCopy({
      targets: [
        {
          src: "components/**/*.less",
          dest: "/",
        },
      ],
      structured: true,
    }),
    lessEntry({
      // 生成的入口文件名
      entry: "components",
      // libPath需要与viteStaticCopy中的dest保持一致
      libPath: "components",
      name: "style",
    }),
  ],
});
// vite-plugin-less-entry.js

import path from "node:path";
import fs from "fs-extra";

const name = "vite-plugin-custom-less-entry";
export const formatConsole = msg => `[${name}] ${msg}`;
/**
 * 生成项目less的入口文件
 */
export default function lessEntryPlugin({ entry, libPath, name }) {
  let outputed = false;
  let rootConfig = null;
  return {
    name,
    apply: "build",
    order: "post",

    configResolved(config) {
      rootConfig = config;
    },

    writeBundle() {
      if (outputed) {
        return;
      }
      outputed = true;

      // 遍历entry下的index.less文件,生成${name}.less文件
      const componentsPath = path.join(rootConfig.root, entry);

      let componentsLessContent = "";
      fs.readdir(componentsPath, (err, files) => {
        files.forEach(file => {
          if (fs.existsSync(path.join(componentsPath, file, "index.less"))) {
            componentsLessContent += `@import "./${libPath}/${path.posix.join(
              file,
              "index.less"
            )}";\n`;
          }
        });

        const lessEntryFile = path.join(
          rootConfig.root,
          rootConfig.build.outDir,
          `${name}.less`
        );
        fs.outputFile(lessEntryFile, componentsLessContent, err => {
          if (err) {
            console.error(formatConsole("Failed to generate less entry file"));
          } else {
            console.info(
              formatConsole("Successfully generated less entry file")
            );
          }
        });
      });
    },
  };
}

配置package.json:

{
  "name": "eric-ui-lib",
  "version": "0.0.2",
  "description": "eric-ui组件库",
  "main": "lib/eric-ui.umd.js",
  "module": "lib/eric-ui.es.js",
  "files": [
    "lib"
  ],
  "keywords": [
    "eric-ui",
    "eric",
    "ui"
  ],
  "author": "Eric",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build",
    "build:lib": "vite build --config ./build/lib.config.js",
    "preview": "vite preview",
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs",
    "docs:preview": "vitepress preview docs"
  },
  "dependencies": {
    "@vitepress-demo-preview/component": "^2.3.2",
    "@vitepress-demo-preview/plugin": "^1.2.3",
    "ant-design-vue": "^3.2.20",
    "fs-extra": "^11.2.0",
    "less-loader": "^12.2.0",
    "vite-plugin-static-copy": "^1.0.6",
    "vue": "^3.4.29"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^5.0.5",
    "@vitejs/plugin-vue-jsx": "^4.0.0",
    "less": "^4.2.0",
    "vite": "^5.3.1",
    "vitepress": "^1.2.3"
  }
}

三、npm发布

npm login 登录,没有注册的自行注册

npm publish

查看npm,即发布成功 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络通信总体框架

目录 网络通信 一、网络通信的定义与基本原理 二、网络通信的组成要素 三、网络通信的应用与发展 网络体系结构 一、网络体系结构的定义与功能 二、OSI七层参考模型 三、网络体系结构的重要性 网络核心与边缘 一、网络核心 1. 定义与功能 2. 组成部分 3. 技术特点 …

昇思25天学习打卡营第19天|LSTM+CRF序列标注

概述 序列标注指给定输入序列,给序列中每个Token进行标注标签的过程。序列标注问题通常用于从文本中进行信息抽取,包括分词(Word Segmentation)、词性标注(Position Tagging)、命名实体识别(Named Entity Recognition, NER)等。 条件随机场&#xff08…

01:spring

文章目录 一:常见面试题1:什么是Spring框架?1.1:spring官网中文1.2:spring官网英文 2:谈谈自己对于Spring IOC和AOP的理解2.1:IOCSpring Bean 的生命周期主要包括以下步骤: 2.2&…

国产化新标杆:TiDB 助力广发银行新一代总账系统投产上线

随着全球金融市场的快速发展和数字化转型的深入推进,金融科技已成为推动银行业创新的核心力量。特别是在当前复杂多变的经济环境下,银行业务的高效运作和风险管理能力显得尤为重要。总账系统作为银行会计信息系统的核心,承载着记录、处理和汇…

MySQL-行级锁(行锁、间隙锁、临键锁)

文章目录 1、介绍2、查看意向锁及行锁的加锁情况3、行锁的演示3.1、普通的select语句,执行时,不会加锁3.2、select * from stu where id 1 lock in share mode;3.3、共享锁与共享锁之间兼容。3.4、共享锁与排他锁之间互斥。3.5、排它锁与排他锁之间互斥3…

离线开发(VSCode、Chrome、Element)

一、VSCode 扩展 使用能联网的电脑 A,在VSCode官网下载安装包 使用能联网的电脑 A,从扩展下载vsix扩展文件 将VSCode安装包和vsix扩展文件通过手段(u盘,刻盘 等)导入到不能联网的离线电脑 B 中 在离线电脑 B 中安装…

计算机网络之无线局域网

1.无线局域网工作方式 工作方式:每台PC机上有一个无线收发机(无线网卡), 它能够向网络上的其他PC机发送和接受无线电信号。 与有线以太网相似,无线局域网也是打包方式发送数据的。每块网卡都有一个永久的、唯一的ID号…

springboot配置扫描生效顺序

文章目录 举例分析项目结构如下noddles-user-backend 两个配置文件noddles-user-job 配置文件noddles-user-server 配置文件问题:server和Job启动时对应加载的数据库配置为哪一个? 总结 在微服务架构中,backend模块会定义一个基础的配置文件,…

java集合(2)

目录 一. Map接口下的实现类 1. HashMap 1.1 HashMap常用方法 2. TreeMap 2.1 TreeMap常用方法 3. Hashtable 3.1 Hashtable常用方法 4.Map集合的遍历 4.1 根据键找值 4.2 利用map中的entrySet()方法 二.Collections类 1.Collections类中的常用方法 三. 泛型 1. 为什…

运维锅总详解系统启动流程

本文详细介绍Linux及Windows系统启动流程,并分析了它们启动流程的异同以及造成这种异同的原因。希望本文对您理解系统的基本启动流程有所帮助! 一、Linux系统启动流程 Linux 系统的启动流程可以分为几个主要阶段,从电源开启到用户登录。每个…

揭秘IP:从虚拟地址到现实世界的精准定位

1.IP地址介绍 1.内网 IP 地址(私有 IP 地址) 内网 IP 地址,即私有 IP 地址,是在局域网(LAN)内部使用的 IP 地址。这些地址不会在公共互联网中路由,因此可以在多个局域网中重复使用。私有 IP 地…

设计模式探索:责任链模式

1. 什么是责任链模式 责任链模式 (Chain of Responsibility Pattern) 是一种行为型设计模式。定义如下: 避免将一个请求的发送者与接收者耦合在一起,让多个对象都有机会处理请求。将接收请求的对象连接成一条链,并且沿着这条链传递请求&…

14-43 剑和诗人17 - ActiveRAG之主动学习

​​​​​ 大型语言模型 (LLM) 的出现开启了对话式 AI 的新时代。这些模型可以生成非常像人类的文本,并且比以往更好地进行对话。然而,它们在仅依赖预训练知识方面仍然面临限制。为了提高推理能力和准确性,LLM 需要能够整合外部知识。 检索…

文件存储的方法一

文章目录 概念介绍实现方法示例代码 我们在上一章回中介绍了"如何实现本地存储"相关的内容,本章回中将介绍如何实现文件存储.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们在上一章回中介绍的本地存储只能存储dart语言中基本类型的数值…

ffmpeg图片视频编辑器工具的安装与使用

title: ffmpeg图片视频编辑器工具的安装与使用 tags: [ffmpeg, 图片, 音频, 视频, 工具, 流媒体] categories: [工具, ffmpeg] FFmpeg是一个开源的命令行工具,广泛用于处理视频和音频文件,包括转换格式、剪辑、混流、解码、编码等。以下是一些基本的FFmp…

Zabbix 的部署和自定义监控内容

前言 一个完整的项目的业务架构包括 客户端 -> 防火墙 -> 负载均衡层(四层、七层 LVS/HAProxy/nginx) -> Web缓存/应用层(nginx、tomcat) -> 业务逻辑层(php/java动态应用服务) -> 数据缓存/持久层(r…

智慧水利的变革之路:如何通过大数据、物联网和人工智能构建高效、智能、可持续的水利管理新模式

目录 一、引言:智慧水利的时代背景与意义 二、大数据:水利管理的数据基石 (一)数据收集与整合 (二)数据分析与挖掘 三、物联网:水利管理的感知神经 (一)智能感知与监…

Git 操作补充:cherry-pick、变基

1. 挑选提交合并 git cherry-pick 对于多分支的代码库,将代码从一个分支转移到另一个分支是一种常见的需求,这可以分成两种情况:一种情况是,你需要另一个分支的所有代码变动,那么就采用 git merge;另一种情…

【Unity2D 2022:UI】制作角色血条

一、创建血底UI 1. 创建画布(Canvas) 2. 在画布上添加血底图像(Image)子物体 二、编辑血底UI 1. 将血底图片拖入源图像(Source Image)中 2. 点击设置为图片的原大小(Set Native Size&#x…

算法重新刷题

基础算法 前缀和 一维前缀和 [USACO16JAN] Subsequences Summing to Sevens S - 洛谷 这一题主要是需要结合数学知识来求解&#xff0c; #include <iostream> #include <cstring> #include <cstdio> #include <algorithm>using namespace std;con…