通过gulp+rollup从零到一搭建前端组件库

news2025/1/10 20:44:18

核心要点

  • 通过 webpack 搭建运行环境
  • 通过 gulp 执行编译流程
  • 通过 rollup 编译组件代码
  • 编写 组件
  • 测试 组件
  • 打包 编译组件
  • 上传 npm

1、通过 webpack 搭建运行环境

这里主要是创建一个可以运行的测试的组件的环境,全局安装vue-cli脚手架,并初始化项目

vue create mtt-component

修改文件夹名称和基本配置的修改

在这里插入图片描述

2、通过 gulp 执行编译流程

安装gulp执行流程中所需要用到的插件

npm install -D  gulp@4.0.2 fs-extra@11.1.0 cross-spawn@7.0.3 sass gulp-sass gulp-postcss autoprefixer@9.8.6

在根目录的build文件底下创建一个gulpfile.js的文件

//gulpfile.js
const gulp = require('gulp');//执行流程
const fs = require('fs-extra');//该插件主要用于操作文件
const spawn = require('cross-spawn');//该插件主要用于运行终端命名
const sass = require('gulp-sass')(require('sass'));//该插件用于将sass编译成css
const postcss = require('gulp-postcss');//该插件处理css
const autoprefixer = require('autoprefixer');//该插件为css自动加前缀
const {pathDist, pathPackagesStyles} = require('./path.config.js');//公共路径配置

//清空组件文件
gulp.task('cleanComponents', done => {
  fs.removeSync(`${pathDist}/cjs`);
  fs.removeSync(`${pathDist}/es`);
  fs.removeSync(`${pathDist}/umd`);
  fs.removeSync(`${pathDist}/styles`);
  done();
});

//打包编译css
gulp.task('buildStyles', done => {
  gulp.src(`${pathPackagesStyles}/**/*.scss`)
      .pipe(sass().on('error', sass.logError))
      .pipe(postcss([
        autoprefixer({
          overrideBrowserslist: [
            'last 2 version',
            '>1%',
            'ios 7'
          ]
        })
      ]))
      .pipe(gulp.dest(`${pathDist}/styles`));
  done();
});

//构建组件
gulp.task('buildComponents', done => {
  spawn.sync('npm run build:rollup', [], {stdio: 'inherit'});
  done();
});

//gulp执行流程
gulp.task('default', gulp.series(['cleanComponents', 'buildStyles', 'buildComponents'], done => {
  console.log('编译成功');
  done();
}));


3、通过 rollup 编译组件代码

安装rollup编译流程中所需要用到的插件

npm install -D  @rollup/plugin-babel@6.0.3 rollup-plugin-vue@5.1.9 @rollup/plugin-node-resolve@15.0.1 @rollup/plugin-commonjs@24.0.1 @rollup/plugin-json@6.0.0 @rollup/plugin-terser@0.4.0  rollup-plugin-postcss@4.0.2

在根目录的build文件底下创建一个rollup.config.js的文件

// rollup.config.js
const babel = require('@rollup/plugin-babel');//在rollup里应用 babel 解析ES6的桥梁
const vue = require('rollup-plugin-vue');//用于处理 .vue文件,针对vue2的文件
const resolve = require('@rollup/plugin-node-resolve');//让rollup可以找到node环境的其他依赖
const commonjs = require('@rollup/plugin-commonjs');//将commonJS代码转译成 esmodule的代码
const json = require('@rollup/plugin-json');//它允许 Rollup 从 JSON 文件导入数据
const terser = require('@rollup/plugin-terser');//压缩代码
const postcss = require('rollup-plugin-postcss');//处理css,它支持css文件的加载、css加前缀、css压缩、对scss/less的支持等等
const postcssPlugin = require('./postcss.config.js');//postcss配置文件
const {getPackageFiles} = require('./utils.js');//获得所有组件路径及名称

//rollup插件基本配置
const getConfigBase = function () {
  return {
    plugins: [
      resolve(),
      vue({
        css: true,
        compileTemplate: true,
        style: {
          postcssPlugins: postcssPlugin
        }
      }),
      json(),
      commonjs(),
      babel({
        babelHelpers: 'bundled',
        exclude: 'node_modules/**',
        extensions: ['.mjs', '.js', '.json', '.ts'],
        presets: [
          [
            '@babel/preset-env',
            {
              'targets': {
                'ie': '8'
              }
            }
          ]
        ]
      }),
      postcss({
        extensions: ['.css', '.scss'],
        extract: true,
        plugins: postcssPlugin
      }),
      terser({
        format: {
          comments: RegExp('eslint-disable')
        }
      })
    ],
    external: [
      'vue',
    ]
  };
};

//rollup文件完整配置
const getConfigArray = (function () {
  let componentsObject = getPackageFiles();
  let formatArray = ['es', 'cjs', 'umd'];
  let filesArray = formatArray.reduce((preArr, format) => {
    let resArr = [];
    let data = getConfigBase();
    data.input = {};
    data.output = {
      banner: '/* eslint-disable */ ',
      dir: `./dist/${format}`,
      format: format,
      name: 'mtt',
      globals: {
        vue: 'Vue' // 告诉rollup全局变量Vue即是vue
      }
    };
    for (let x of componentsObject) {
      let item = {};
      item[x.inputName] = x.inputPath;
      data.input = {
        ...data.input,
        ...item
      };
      if (format === 'umd') {
        break;
      }
    }
    resArr.push(data);
    return preArr.concat(resArr);
  }, []);
  return filesArray;
})();

module.exports = getConfigArray;

4、编写组件

现在chatgpt这么火,借助chatgpt编写了个简单的button组件

在这里插入图片描述
然后,在button文件夹下,建立一个index.js,用于导出单个组件

import button from './button.vue'

// 为组件提供 install 安装方法,供按需引入
button.install = function (Vue) {
  Vue.component(button.name, button)
}

// 默认导出组件
export default button

然后,在components的根目录下,建立一个index.js,该文件用于导出所有组件

// 导入按钮
import MttButton from './button'

// 存储组件列表
const components = [
  MttButton
]

// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
const install = function (Vue) {
  // 判断是否安装
  if (install.installed) return
  // 遍历注册全局组件
  components.map(component => Vue.component(component.name, component))
}

// 判断是否是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
  install(window.Vue)
}

export default {
  // 导出的对象必须具有 install,才能被 Vue.use() 方法安装
  install,
  // 以下是具体的组件列表
  MttButton
}

5、测试组件

在业务端引入组件

在这里插入图片描述

运行到浏览器,运行成功了,得出了预期的结果

在这里插入图片描述

6、打包编译组件

终端运行打包命令

 npm run build

打包完后,得到dist目录下的打包后的代码,为了方便测试,我们先不上传到npm,而是通过npm link软连接的方式,引入组件再次测试,得到一样的结果

在这里插入图片描述

7、上传 npm

配置 package.json,通过npm publish即可上传至npm,要注意的事,上传npm时,不要用淘宝镜像,切换npm自身的镜像,否则会有10分钟的延迟

在这里插入图片描述

到npm官网查看下,发现我们的发布的组件库已经成功了

在这里插入图片描述

8、附加说明

  • 该组件库可以支持全量引入和按需引入,关于按需引入方面,可以参考 element的按需引入方式
  • 目前该组件库的基础架构是针对vue2的,若想针对vue3进行开发,只需要改变rollup的部分插件即可,不过建议可以和vite架构结合,后续我看看搞个vite版本的
  • 文章中的代码地址在这里:任意门-BiuBiu

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

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

相关文章

代码提交格式化工具---prettier的使用与配置

为什么要格式化代码 我们在合作写项目的时候,因为每个人的代码书写习惯以及编辑器的配置都不相同,这样就可能导致我们写的代码的格式都完全不一样,有的代码格式看起来也比较难以阅读,那么prettierd就由此产生了。 Prettier是一个…

题集-链表分割

链表分割_牛客题霸_牛客网 (nowcoder.com) 链表去做的话,可以分为带哨兵位和不带哨兵位两种,但是不带哨兵位会更麻烦一些,更容易出现空指针问题。 这里两种思路都是:将小于x的结点尾插到less链表中,将大于x的结点尾插到…

数据结构之队列,实现队列的增删改查

目录 一、队列的定义 二、队列的实现 1.使用链表来实现队列 2.实现队列的接口 初始化队列 void QueueInit(Queue *pq) 队尾入队列 void QueuePush(Queue *pq,QDataType data) 队头出队列 void QueuePop(Queue *pq) 获取队列头部元素 QDataType QueueFront(Queue *pq) …

uni-app获取手机号-获取用户地理位置-根据位置获取经纬度跳转高德

一.获取手机号 1.获取手机号首先要先登录拿到code,用code去获取session_key 2.获取 code需要知道自己的AppID(小程序ID)和AppSecret(小程序密钥) 3.解密后得到手机号 登录微信公众平台拿到自己的AppID(小程序ID)和AppSecret(小程序密钥) 微信公众平台 获取sessio…

【Java EE 初阶】如何保证线程安全二

目录 1.线程不安全是什么? 2.线程不安全的成因 3.解决线程不安全之一Synchronized关键字(监视器锁) 1.Synchronized使用方法 2.锁对象是什么? ​3.锁对象的练习 4.Synchronized的特性 1.互斥性 2.刷新内存 3.可重入 5.总…

事务及分布式事务解决方案

基础概念 1.1.事务 事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败。 1.2.本地事务 在计算机系统中,更多的是通过关系型数据库来控制事务,利用数据库本身的事务特性来实现&a…

SAP 从入门到放弃系列之批次追溯功能

首先执行MB57,建立批次追溯关系,并存储在CHVW表。根据情况选择要追溯的期间,在过账日期范围内填写。 不勾选‘基于清单显示’,为ALV显示结果 勾选‘基于清单显示’,为清单显示结果 执行MB56,查询批次追溯 可以设置显示…

【.NET AI Books 前言】Azure OpenAI Service 入门

本书是为 .NET 开发者而写的,让 .NET 开发者能快速掌握 Azure OpenAI Service 的使用技巧。 ChatGPT 的到来意味着我们已经置身于 AI 引起的全新变革中,作为开发者你可能将面临几种改变: GPT 模型到来后,如何去架构好企业解决方案…

Dex-Net 2.0<论文>

题目:Deep Learning to Plan Robust Grasps with Synthetic Point Clouds and Analytic Grasp 引言 传统抓取方法的局限性 缺乏泛化能力需要大量计算资源和手工标注数据【前两种依赖物体形状、材料、质量等先验知识通常要对物体建模姿态评估运动学分析】只能处理…

【C语言】深入理解注释

文章目录 一. 预处理阶段对注释的处理二. 注释使用时的注意事项1. C风格的注释无法嵌套使用2. 基本注释注意事项3. 注释导致的二义性 四. 关于注释的一个使用建议 一. 预处理阶段对注释的处理 我们知道一个源文件要变成可执行程序的话,首先要经过预处理&#xff0c…

Vtk7.1.1+PCL1.12.0安装

错误可参考:Ubuntu20.04 编译 pcl1.8可能出现的问题 安装参考1:ubuntu20.04下安装pcl_ubuntu安装pcl_Yuannau_jk的博客-CSDN博客 安装参考2:Ubuntu20.04 安装pcl详细教程_ubuntu20.04安装pcl_LYiiiiiii的博客-CSDN博客 安装参考3&#xff1a…

涨知识!你不知道的中国手机号码的编码和划分规则

引言 在当今信息化的时代,移动电话号码已经成为人们日常生活中必不可少的联系方式。中国作为世界上拥有庞大人口数量的国家之一,移动电话号码的编码和划分显得尤为重要。 中国的移动电话号码分为三大运营商,每个运营商又有自己的号码段&…

Spring Security OAuth2.0(三)-----基于Redis存储和JDBC存储

问题 令牌往哪里存? 客户端信息入库 第三方应用优化 1.令牌往哪里存? 在我们配置授权码模式的时候,有两个东西当时存在了内存中: InMemoryAuthorizationCodeServices 这个表授权码存在内存中。InMemoryTokenStore 表示生成的令…

open3D

一、说明 对于点云 处理,这里介绍哦pen3d,该软件和opencv同样是interl公司的产品。 Open3D 是一个开源库,支持快速开发处理 3D 数据的软件。 Open3D 前端在 C 和 Python 中公开了一组精心挑选的数据结构和算法。后端经过高度优化,…

Spring Boot处理CORS跨域请求的三种方法

1 前言 Springboot跨域问题,是当前主流web开发人员都绕不开的难题。但我们首先要明确以下几点 跨域只存在于浏览器端,不存在于安卓/ios/Node.js/python/ java等其它环境跨域请求能发出去,服务端能收到请求并正常返回结果,只是结…

05-权限分配 尚筹网

权限控制 权限控制机制的本质就是“用钥匙开锁”。 在实现权限控制之前,这里先完成给Admin分配Role和给Role分配Auth的功能。 一、给Admin分配Role 目标 ​ 通过前端页面操作,将Admin与Role之间的关系保存到数据库 思路 ​ 给下面的按钮&#xff…

【ED合集】事件检测的文章

1 CorED: Incorporating Type-level and Instance-level Correlationsfor Fine-grained Event Detection 论文来源:SIGIR 2022(CCF A类会议) 论文链接:https://dl.acm.org/doi/pdf/10.1145/3477495.3531956 代码链接:GitHub - JiaweiSheng…

抖音小程序|基于天气API实现天气预报功能

文章目录 一、前言包含了功能UI展示 二、开发前的准备三、开发步骤1.app.js 配置2.pages/index.js 演示二维码源码在百度网盘下载 一、前言 参考老版iPhone自带的天气预报APP。目前只有一个界面UI, 后续会更新出更多功能; 包含了功能 - 实况预报 - 未来48小时 - 未来一周的天…

动态gif图片如何在线做?轻松实现图片在线生成gif

常见的jpg、png格式的静态图片想要变成gif格式的动态图片时,要怎么办呢?有没有什么简单实用的gif制作工具呢? 一、什么工具能够在线制作gif? GIF中文网作为一款专业的gif制作(https://www.gif.cn/)工具&a…

Golang - slice 内部实现原理解析

Golang - slice 内部实现原理解析 一.Go中的数组和slice的关系 1.数组 在几乎所有的计算机语言中,数组的实现都是一段连续的内存空间,Go语言数组的实现也是如此,但是Go语言中的数组和C语言中数组还是有所不同的 C语言数组变量是指向数组第…