rollup 插件开发示例

✨专栏介绍

Rollup专栏是一个专门介绍Rollup打包工具的系列文章。Rollup是一个现代化的JavaScript模块打包工具,它可以将多个模块打包成一个或多个文件,以提高应用程序的性能和加载速度。

在Rollup专栏中,您将学习到如何安装和配置Rollup,以及如何使用它来打包JavaScript模块。我们将深入探讨不同类型的模块(如CommonJS、ES6等)的处理方式,以及如何处理依赖关系和循环引用。

此外,我们还将介绍一些常用的插件和配置选项,以帮助您更好地使用Rollup。您将学习到如何使用动态导入来实现按需加载,如何优化打包结果以减小文件大小,并了解与其他工具(如Babel、TypeScript等)集成使用的技巧。

通过阅读Rollup专栏,您将掌握使用这个强大工具的基本知识,并学会一些高级特性和技巧。让我们一起开始吧!

在这里插入图片描述

文章目录

    • ✨专栏介绍
    • 引言
    • @rollup/pluginutils介绍
    • 插件上下文
    • 自定义插件
    • JSON插件示例
    • 图片读取
    • 总结
    • 😶 写在结尾


引言

Rollup是一个JavaScript模块打包器,它可以将多个模块打包成一个单独的文件,以便在浏览器中使用。与其他打包工具相比,Rollup的主要优势在于它可以生成更小、更快的代码。在本文中,我们将深入了解Rollup的插件开发。

@rollup/pluginutils介绍

@rollup/pluginutils是一个官方提供的Rollup插件开发工具库,它提供了一些实用的函数和工具,用于简化插件开发过程中的一些常见任务。

该工具库提供了以下常用的函数和工具方法:

  1. createFilter(include?: string | RegExp | (string | RegExp)[], exclude?: string | RegExp | (string | RegExp)[]): FilterPattern

    • 用于创建一个过滤器,可以根据指定的包含和排除规则来过滤文件。
    • 可以传入字符串、正则表达式或字符串/正则表达式数组作为参数。
    • 返回一个函数,该函数接受文件路径作为参数,并返回一个布尔值,表示该文件是否应该被处理。
  2. makeLegalIdentifier(name: string): string

    • 用于将给定的字符串转换为合法的JavaScript标识符。
    • 主要用于处理可能包含非法字符或保留字的模块名称。
  3. dataToEsm(data: any, options?: DataToEsmOptions): string

    • 将给定的数据转换为ES模块导出语法的字符串。
    • 可以传入选项对象来自定义导出语法。
  4. attachScopes(ast: any, scope: Scope): void

    • 将作用域信息附加到AST(抽象语法树)节点上。
    • 可以帮助插件在处理代码时正确地处理变量作用域。

这些函数和工具可以帮助开发者更方便地处理文件过滤、标识符转换、数据转换和作用域处理等常见任务,提高插件开发的效率和可靠性。

插件上下文

插件上下文

这个其实也是插件中很常用的一些api,可以通过 this 从大多数钩子中访问一些实用函数和信息位。

自定义插件

rollup-plugin-custom

import { createFilter } from '@rollup/pluginutils';
import path from "path";export default function customPlugin(options = {}) { const filter = createFilter(options.include, options.exclude);return {name: "custom-plugin",transform(code, id) { if (!filter(id)) { return null;}const parsedCode = this.parse(code);const source = `${code} \n\n ${JSON.stringify(parsedCode, null, 2)}`;const fileName = path.basename(id, path.extname(id));console.log(fileName);if (options.emitFile) { this.emitFile({type: "asset",fileName: fileName + ".txt",source})}}}}

首先,通过 createFilter 函数创建一个过滤器,用于确定哪些文件需要被处理。options.includeoptions.exclude 分别指定了需要包含和排除的文件。

然后,返回一个对象,其中包含了插件的名称和一个 transform 方法。transform 方法会在每个模块被转换时调用。 在 transform 方法中,首先使用过滤器检查当前模块是否需要处理。如果不需要处理,则返回 null

接下来,使用 this.parse(code) 方法解析代码,并将解析结果与原始代码拼接成一个新的字符串 source。 然后,使用 path.basename(id, path.extname(id)) 获取当前模块的文件名(不包含扩展名),并打印输出。 如果设置了 options.emitFile 为 true,则调用 this.emitFile() 方法将处理后的代码作为一个 asset 文件输出。输出的文件名为当前模块的文件名加上 .txt 扩展名。

最后,这个插件可以通过在 Rollup 配置文件中引入并添加到插件列表中来使用。

rollup.config.mjs

import { defineConfig } from "rollup";
import customPlugin from "./plugins/rollup-plugin-custom.js";export default defineConfig({input: "src/index.js",output: {dir: "dist",format: "esm",sourcemap: true,},plugins: [customPlugin({emitFile:true})],
});

JSON插件示例

rollup默认是不能直接读取json文件的内容的,我们自己写一个插件处理一下。

安装

npm install @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/pluginutils -D

rollup-plugin-json

import { createFilter,dataToEsm } from '@rollup/pluginutils';
import path from 'path';export default function myJson(options = {}) {// rollup 推荐每一个 transform 类型的插件都需要提供 include 和 exclude 选项,生成过滤规则const filter = createFilter(options.include, options.exclude);return {name: 'rollup-plugin-json',transform: {order: "pre",handler(code, id) {if (!filter(id) || path.extname(id) !== '.json') return null;try {const parse = JSON.stringify(JSON.parse(code));return {// dataToEsm 将数据转换成esm模块// 其实就是 export default "xxx"code: dataToEsm(parse), map: { mappings: '' }};} catch (err) { const message = 'Could not parse JSON file';this.error({ message, id, cause: err });return null;}}}};
}

首先,通过 createFilter 方法创建一个过滤器,用于确定哪些文件需要被处理。options.includeoptions.exclude 分别指定了需要包含和排除的文件。

然后,返回一个对象,其中包含了插件的名称和一个 transform 对象。transform 对象中有两个属性:orderhandler

  • order: "pre" 表示这个插件在转换过程中应该在其他插件之前执行。
  • handler(code, id) 是一个处理函数,它会在每个模块被转换时调用。

handler 函数中,首先使用过滤器检查当前模块是否需要处理,并且判断当前模块是否是 JSON 文件。如果不需要处理或者不是 JSON 文件,则返回 null

接下来,尝试将代码解析为 JSON 对象,并使用 dataToEsm(parse) 方法将解析后的对象转换为 ES 模块格式的代码。然后返回一个对象,其中包含了转换后的代码和一个空的 Source Map。

如果解析过程中出现错误,则会捕获错误并通过调用 this.error() 方法抛出错误信息,并返回 null

最后,这个插件可以通过在 Rollup 配置文件中引入并添加到插件列表中来使用。它会在构建过程中将 JSON 文件转换为 ES 模块格式的代码。

页面使用

import pkg from "../package.json";
console.log(pkg.name)

图片读取

mini-svg-data-uri是一个用于将SVG图像转换为mini data URI格式的JavaScript库。它可以将SVG图像的内容转换为base64编码,并生成一个data URI,以便在HTML或CSS中直接使用。

安装mini-svg-data-uri

npm install mini-svg-data-uri -D

rollup-plugin-image

import { createFilter,dataToEsm } from "@rollup/pluginutils";
import { extname,resolve,basename,relative,normalize,sep } from "path";
import fs from "fs";
import svgToMiniDataURI from "mini-svg-data-uri";const defaults = {fileSize: 1024 * 4,target: "./dist",include: null,exclude: null,
}const mimeTypes = {".png": "image/png",".jpg": "image/jpeg",".jpeg": "image/jpeg",".gif": "image/gif",".svg": "image/svg+xml",".ico": "image/x-icon",".webp": "image/webp",".avif": "image/avif"
}const getDataUri = ({ format, isSvg, mime, source }) =>isSvg ? svgToMiniDataURI(source) : `data:${mime};${format},${source}`;const ensureDirExists = async (dirPath) => { try {await fs.promises.access(dirPath);return true;} catch (err) { // 文件夹不存在就创建文件夹try {await fs.promises.mkdir(dirPath, { recursive: true });return true;}catch (err) { console.error(err);return false;}}
}export default function myImage(opts = {}) { const options = Object.assign({}, defaults, opts);const filter = createFilter(options.include, options.exclude);return {name: "my-image",async transform(code, id) { if (!filter(id)) return null;// 获取后缀const ext = extname(id);// 判断是否是图片if(!mimeTypes.hasOwnProperty(ext)) {return null;}// 获取图片的mime类型const mime = mimeTypes[ext];// 判断是否svgconst isSvg = mime === mimeTypes[".svg"];// 图片format格式const format = isSvg ? "utf-8" : "base64";// 目标路径const assetsPath = resolve(process.cwd(), options.target);//获取文件名const fileName = basename(id);// 最终文件路径const filePath = resolve(assetsPath, fileName);let relativePath = normalize(relative(process.cwd(), filePath));relativePath = relativePath.substring(relativePath.indexOf(sep) + 1);try {// 如果图片文件过大,就应该直接拷贝文件,返回文件路径// 读取图片文件大小与设置的大小进行比较const stat = await fs.promises.stat(id);if (stat.size > options.fileSize) {// 文件的拷贝,以及对象的返回// 文件拷贝,无非就是文件源路径,目标路径// copyFile 拷贝文件地址的文件夹必须存在// 如果文件夹不存在,那么就创建文件夹const dirExists = await ensureDirExists(assetsPath);dirExists && await fs.promises.copyFile(id, filePath);return {code: dataToEsm(relativePath), //返回拷贝之后处理的路径map: { mappings: "" }}} else {// 否则转换为base64格式// 读取文件const source = await fs.promises.readFile(id, format);return {code: dataToEsm(getDataUri({ format, isSvg, mime, source })),map: { mappings: "" }}}} catch (err) { const message = "图片转换失败:" + id;this.error({ message, id, cause: err });return null;}}}
}
  1. createFilter(include, exclude): 这个函数来自于@rollup/pluginutils包,用于创建一个过滤器函数,根据给定的include和exclude规则来判断文件是否需要被处理。
  2. extname(id): 这个函数来自于path模块,用于获取文件路径的扩展名。
  3. resolve(...paths): 这个函数来自于path模块,用于将多个路径片段解析为绝对路径。
  4. basename(path): 这个函数来自于path模块,用于获取文件路径的基本名称(不包含目录部分)。
  5. relative(from, to): 这个函数来自于path模块,用于获取从一个路径到另一个路径的相对路径。
  6. normalize(path): 这个函数来自于path模块,用于规范化给定的路径字符串。
  7. sep: 这是一个常量,表示操作系统特定的路径分隔符(例如,在Windows上是反斜杠``)。
  8. fs.promises.access(path): 这是一个Promise-based API,用于检查指定路径是否可访问。
  9. fs.promises.mkdir(path, options): 这是一个Promise-based API,用于创建指定路径的目录。options参数可以包含递归选项,以便创建多级目录。
  10. fs.promises.stat(path): 这是一个Promise-based API,用于获取指定路径的文件信息,例如文件大小。
  11. fs.promises.copyFile(src, dest): 这是一个Promise-based API,用于将源文件复制到目标文件。
  12. fs.promises.readFile(path, encoding): 这是一个Promise-based API,用于读取指定路径的文件内容。encoding参数用于指定读取的编码格式。
  13. dataToEsm(value): 这个函数来自于@rollup/pluginutils包,用于将给定的值转换为ES模块导出语法。
  14. svgToMiniDataURI(svg): 这个函数来自于mini-svg-data-uri包,用于将SVG图像转换为mini data URI格式。

在插件的transform方法中,首先使用过滤器函数判断是否需要处理当前文件。然后根据文件扩展名判断是否为图片文件,并获取对应的MIME类型。接下来根据配置的目标路径和文件名构建最终的文件路径。如果图片文件大小超过了设置的阈值,则直接拷贝该文件到目标路径,并返回拷贝后的路径。否则,将图片内容转换为base64格式,并返回对应的data URI。

rollup.config.mjs

import { defineConfig } from "rollup";
import imagePlugin from './plugins/rollup-plugin-image.js'export default defineConfig({input: "src/index.js",output: {dir: "dist",format: "esm",sourcemap: true,},plugins: [imagePlugin({fileSize: 1024 * 10,target: './dist/assets'})],
});

总结

  1. Rollup插件机制允许开发者通过编写自定义插件来扩展Rollup的功能。

  2. 插件是由一个或多个钩子函数组成的,钩子函数定义了在打包过程中的不同阶段执行的操作。

  3. 常用的钩子函数有optionsresolveIdloadtransformgenerateBundle,每个钩子函数都有特定的调用时机和参数。

  4. 插件可以通过返回一个Promise对象来处理异步操作。

  5. Rollup插件可以使用第三方库来辅助开发,例如rollup-pluginutils用于创建过滤器。

  6. 开发者可以根据自己的需求编写自定义插件,并将其添加到Rollup配置中,以实现各种功能扩展,例如压缩代码、处理CSS、加载和解析JSON等。

  7. 插件开发需要注意性能和代码质量,避免不必要的操作和副作用。

通过使用Rollup插件机制,开发者可以灵活地定制打包过程,并根据项目需求添加各种功能扩展。这使得Rollup成为一个强大而灵活的JavaScript模块打包工具。


😶 写在结尾

前端设计模式专栏
在这里插入图片描述
设计模式是软件开发中不可或缺的一部分,它们帮助我们解决了许多常见问题,并提供了一种优雅而可靠的方式来构建应用程序。在本专栏中,我们介绍了所有的前端设计模式,包括观察者模式、单例模式、策略模式等等。通过学习这些设计模式,并将其应用于实际项目中,我们可以提高代码的可维护性、可扩展性和可重用性。希望这个专栏能够帮助你在前端开发中更好地应用设计模式,写出高质量的代码。点击订阅前端设计模式专栏

Vue专栏
在这里插入图片描述
Vue.js是一款流行的JavaScript框架,用于构建用户界面。它采用了MVVM(Model-View-ViewModel)的架构模式,通过数据驱动和组件化的方式,使开发者能够更轻松地构建交互性强、可复用的Web应用程序。在这个专栏中,我们将深入探讨Vue.js的核心概念、组件开发、状态管理、路由和性能优化等方面的知识。我们将学习如何使用Vue.js构建响应式的用户界面,并探索其强大的生态系统,如Vue Router和Vuex、Pinia。通过学习这些内容,你将能够成为一名熟练的Vue.js开发者,并能够应用这些知识来构建复杂而高效的Web应用程序。点击订阅Vue专栏

JavaScript(ES6)专栏在这里插入图片描述
JavaScript是一种广泛应用于网页开发和后端开发的脚本语言。它具有动态性、灵活性和易学性的特点,是构建现代Web应用程序的重要工具之一。在这个专栏中,我们将深入探讨JavaScript语言的基本语法、DOM操作、事件处理、异步编程以及常见算法和数据结构等内容。此外,我们还将介绍ES6(ECMAScript 2015)及其后续版本中引入的新特性,如箭头函数、模块化、解构赋值等。通过学习这些内容,你将能够成为一名熟练的JavaScript开发者,并能够应用这些知识来构建出高质量和可维护的Web应用程序。点击订阅JavaScript(ES6)专栏

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

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

相关文章

专车数据层架构进化往事:好的架构是进化来的,不是设计来的

很多年前,读了子柳老师的《淘宝技术这十年》。这本书成为了我的架构启蒙书,书中的一句话像种子一样深埋在我的脑海里:“好的架构是进化来的,不是设计来的”。 2015 年,我加入神州专车订单研发团队,亲历了专…

将DOM结构转换成图片保存至本地或保存至剪切板

在新业务需求中,碰到这样一个场景,需要将后端返回的表格数据,保存至本地或者保存至剪切板,直接发送给用户使用。 1. 将内容转换成图片并保存至本地 1.1 交互效果 如图所示,想要点击复制按钮后,将下面这个…

Talk | 香港科技大学博士生陈竞晔:TextDiffuser系列让扩散模型渲染文本不再是难题

本期为TechBeat人工智能社区第560期线上Talk。 北京时间1月3日(周三)20:00,香港科技大学在读博士生—陈竞晔的Talk已准时在TechBeat人工智能社区开播! 他与大家分享的主题是: “TextDiffuser系列让扩散模型渲染文本不再是难题”,介绍了他的团…

2020年认证杯SPSSPRO杯数学建模D题(第一阶段)让电脑桌面飞起来全过程文档及程序

2020年认证杯SPSSPRO杯数学建模 D题 让电脑桌面飞起来 原题再现: 对于一些必须每天使用电脑工作的白领来说,电脑桌面有着非常特殊的意义,通常一些频繁使用或者比较重要的图标会一直保留在桌面上,但是随着时间的推移,…

如何无需公网IP实现远程访问Windows本地WebDAV服务中存储文件

文章目录 1. 安装IIS必要WebDav组件2. 客户端测试3. cpolar内网穿透3.1 打开Web-UI管理界面3.2 创建隧道3.3 查看在线隧道列表3.4 浏览器访问测试 4. 安装Raidrive客户端4.1 连接WebDav服务器4.2 连接成功4.2 连接成功总结: 自己用Windows Server搭建了家用NAS主机&…

Vue+ElementUI笔记(1)

一、表格 1.上移、下移和移除功能 需求:有时我们会面对类似这样的表格 图中的上移,下移功能需求明显要求我们改变两行数据的顺序。在实际开发中这种功能一般由后台来做,因为列表数据一般从后台获取刷新。即是我们点击”上移“,向…

mac环境下安装部署mysql5.7

下载安装包 进入官网下载MySQL5.7的安装包 https://www.mysql.com/downloads/ 安装包下载完成后双击pkg文件进行安装,无脑点下一步即可,注意安装完成后记得保存最后弹出框的密码 进入系统偏好设置,找到mysql,开启mysql服务…

maven:在maven中使用tomcat7插件

1、在pom.xml中添加tomcat7插件 <build><!-- Embedded Apache Tomcat required for testing war --><plugin><groupId>org.apache.tomcat.maven</groupId><artifactId>tomcat7-maven-plugin</artifactId><version>2.2</ver…

springboot漫画网站源码和论文

随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&#xf…

面试官:如何实现两栏布局,右侧自适应?三栏布局中间自适应呢?

面试官&#xff1a;如何实现两栏布局&#xff0c;右侧自适应&#xff1f;三栏布局中间自适应呢&#xff1f; 一、背景 在日常布局中&#xff0c;无论是两栏布局还是三栏布局&#xff0c;使用的频率都非常高 两栏布局 两栏布局实现效果就是将页面分割成左右宽度不等的两列&am…

ROS学习记录:在ROS中用C++实现激光雷达避障

前言 本文建立在成功获取激光雷达数据的基础上&#xff0c;详细参考 在ROS中用C实现获取激光雷达的数据 一、实现思路 二、在VScode中打开之前编写好的lidar_node.cpp 三、在lidar_node.cpp中写入如下代码 #include <ros/ros.h> #include <std_msgs/String.h> …

Mysql的四大引擎,账号管理,数据库的建立

数据库存储引擎查看 Support字段说明 default的为默认引擎 YES表示可以使用 NO表示不能使用 命令 SHOW ENGINES 四大引擎 MEMORY 使用场景&#xff1a;由于易失性&#xff0c;可以用于存储在分析中产生的中间表 特点 所有的数据都保存在内存中&#xff0c;一旦服务器重启&…

[每周一更]-(第55期):Go的interface

参考地址 https://juejin.cn/post/6978322067775029261https://gobyexample.com/interfaceshttps://go.dev/tour/methods/9 介绍下Go的interface 在Go语言中&#xff0c;interface是一种特殊的数据类型&#xff0c;用于定义一组方法的规范。它描述了一个对象可以具备的行为&…

ElasticSearch自定义算分排序(Function Score Query)

使用 function score query&#xff0c;可以修改文档的相关性算分 (query score)&#xff0c;根据新得到的算分排序。 目录 Function Score Query 案例 Function Score Query 几种默认的计算分值的函数&#xff1a; Weight:为每一个文档设置一个简单而不被规范化的权重Fie…

Centos8破解Root密码

注&#xff1a;Centos7同理。 1.重启Centos8系统后&#xff0c;在启动页面中选中第一行&#xff0c;按【e】键进入界面。 2.找到linux开头所在行的找到“ro”改为上“rw init/sysroot/bin/bash”&#xff0c;同时按下【Ctrl】【X】跳转到紧急模式。 3.在紧急模式下&#xff0c…

UniversalTransformer with Adaptive Computation Time(ACT)

原论文链接&#xff1a;https://arxiv.org/abs/1807.03819 Main code import torch import numpy as npclass PositionTimestepEmbedding(torch.nn.Module):def forward(self, x, t):device x.devicesequence_length x.size(1)d_model x.size(2)position_embedding np.arr…

Qt界面篇:Qt停靠控件QDockWidget、树控件QTreeWidget及属性控件QtTreePropertyBrowser的使用

1、功能介绍 本篇主要使用Qt停靠控件QDockWidget、树控件QTreeWidget及Qt属性控件QtTreePropertyBrowser来搭建一个简单实用的主界面布局。效果如下所示。 2、控件使用详解 2.1 停靠控件QDockWidget QDockWidget可以停靠在 QMainWindow 内或作为桌面上的顶级窗口浮动。默认值…

基于OpenCV的透视变化

基本概念 透视变换(Perspective Transformation)是仿射变换的一种非线性扩展,是将图片投影到一个新的视平面(Viewing Plane)&#xff0c;也称作投影映射(Projective Mapping)。 原理&#xff1a;将二维的图片投影到一个三维视平面上&#xff0c;然后再转换到二维坐标下&#…

everything 本地文件搜索工具 完胜WIndows搜索 速度99% 超级给力

"Everything" 是一个 Windows 平台上的免费软件&#xff0c;它是一款功能强大的本地文件搜索工具。它允许用户在计算机上快速而准确地搜索文件和文件夹。以下是一些 "Everything" 的主要特点&#xff1a; 实时搜索&#xff1a; "Everything" 提供…

【小沐学NLP】Python实现TF-IDF算法(nltk、sklearn、jieba)

文章目录 1、简介1.1 TF1.2 IDF1.3 TF-IDF2.1 TF-IDF(sklearn)2.2 TF-IDF(nltk)2.3 TF-IDF(Jieba)2.4 TF-IDF(python) 结语 1、简介 TF-IDF&#xff08;term frequency–inverse document frequency&#xff09;是一种用于信息检索与数据挖掘的常用加权技术。TF是词频(Term Fr…