当前位置: 首页 > news >正文

如何编写一个 npm 插件?

提到写 npm 插件,很多没搞过的可能第一感觉觉得很难,无从下手,其实不然。

我们甚至写个简单的 console.log('hello word'),都是可以当成一个插件发布上去的。

其实无从下手的主要难点还是在于你的具体要做的功能逻辑,这个理清楚了,写插件并没有想象的那么难。

接下来,我们来看下具体插件编写的思路。

一、首先,建个项目

拿我想做一个 h5 前端的水印插件为例,思路就是用 canvas 去绘制,创建 dom,然后用 js 把这个 dom 添加到页面中去。

根据这个思路,我要用到的是纯纯的 js 就够了。但是我的文件夹不能乱放吧,该有的代码规范总归还得尽量保持一下(日行一善)。

那就弄个src目录,入口文件index.js,主逻辑文件watermark.js,公共库文件utils.js,全局配置文件config.js等等。这样一套下来,目录结构也就起来了。

在这里插入图片描述

这个是我最终的插件目录,就大概参考一下。

再想想,怎么在入口文件index.js引入我们的主逻辑,或者在xx.js中引入xxx.js?

是不是想说,用importexport呗。

是的!但是这种语法,有的浏览器(拿IE举例)不认识啊,或者你想用一些 es6+ 语法、ts、eslint等等,那我们就得用到打包工具,把它转义成浏览器能识别的 js 代码。

二、打包工具选择

2.1 webpack 和 rollup

提到打包工具,日常搬砖过程中,最常用的应该是webpackrollup,这里对它俩的区别不过多的介绍,大概的理解为一般涉及到web页面开发相关的插件就用webpack,纯js的功能性插件就用rollup。

这里用rollup来举例,相比webpack,它的配置对新手更容易理解一些。

三、依赖项安装

3.1 安装 rollup、ts

  • rollup
  • typescript
  • rollup-plugin-commonjs 支持识别commonjs类型
  • @rollup/plugin-typescript 支持编译ts
  • (可根据需要安装更多的依赖)
npm install -s-d rollup typescript rollup-plugin-commonjs @rollup/plugin-typescript

3.2 安装 babel

  • @babel/core
  • @babel/preset-env
  • rollup-plugin-babel
  • rollup-plugin-terser
  • (可根据需要安装更多的依赖)
npm install -d @babel/core @babel/preset-env rollup-plugin-babel rollup-plugin-terser

四、依赖项配置

4.1 rollup配置

rollup的作用就是把我们最终的源代码进行打包压缩,生成最终的插件文件。这里拿最主要的 3 个配置属性来讲一下。 也可以参考这个配置 package.json、rollup.config.js

{input: "src/index.ts", // 入口文件,必须plugins: [rollupTypescript(),commonjs({exclude: "node_modules",}),babel({exclude: "node_modules",}),terser(),],output: {// 必须 (如果要输出多个,可以是一个数组)file: "lib/esm/index.js", // 出口文件,必须format: "esm", // 必须banner: "/* watermark version 🌹" + version + " */",footer: "/* up up up */",sourcemap: false,},
}
  • input,入口文件,就是源代码的入口,了解更多
  • plugins,使用依赖项的数组,了解更多
  • output,对象,打包生成的文件配置,了解更多
    • file, 插件代码打包生成的位置
    • format,生成插件的格式,支持commonjs、es模块、iife立即执行函数等等多种格式
    • sourcemap,是否生成sourcemap
    • …等等

4.2 ts配置

{"compilerOptions": {"allowUnreachableCode": true, // 不报告执行不到的代码错误。"allowUnusedLabels": false, // 不报告未使用的标签错误"alwaysStrict": false, // 以严格模式解析并为每个源文件生成 "use strict"语句"baseUrl": "./src", // 工作根目录"preserveConstEnums": true, // 使用 const enum 产生内联成员"experimentalDecorators": true, // 启用实验性的ES装饰器"sourceMap": false,"noImplicitAny": false, // 是否默认禁用 any"removeComments": true, // 是否移除注释"forceConsistentCasingInFileNames": true, //禁止对同一个文件的不一致的引用。"paths": {// 指定模块的路径,和baseUrl有关联"@/*": ["./*"]},"types": ["node"],"target": "es5", // 编译成什么版本"module": "es6", // 指定生成哪个模块系统代码"outDir": "examples/monitorHybird/", // 输出目录"declaration": true, // 是否自动创建类型声明文件"declarationDir": "examples/monitorHybird/types/", // 类型声明文件的输出目录"typeRoots": [// 指定某个文件夹的声明文件"node_modules/@types"],"allowJs": true, // 允许编译javascript文件。"lib": [// 编译过程中需要引入的库文件的列表"es5","es2015","es2016","es2017","es2018","dom"]},"files": ["src/index.ts"],"include": ["src/**/*"],"exclude": ["node_modules", "**/*.spec.ts"]
}

五、主逻辑编写

开发前,你要考虑这个插件对外提供哪些属性或方法,它发布了以后别人怎么去用。

import watermark from "watermark-h5";watermark.init({parentDomName: 'body',        // string 父节点dom选择器名字show: true,                   // boolean 水印开关color: 'rgba(0, 0, 0, 0.06)', // string 水印色值title: '严禁外传',             // string 显示的水印文本width: 200,                  // number 单个水印宽度height: 200,                 // number 单个水印高度fontNum: 15,                 // number 水印字体大小rotate: -25,                 // number 旋转角度zIndex: 9999                 // number 层级
});

拿这个水印插件为例,如上述代码的使用方式,开发的时候就考虑以下 3 点。

  • 计划给用户提供一个实例对象
  • 挂载有init方法
  • 支持约定格式的参数传递
  1. 给用户提供一个实例对象

目的是为了让用户能够调用身上的方法,写法其实很简单,如下图所示。
在这里插入图片描述

这里当然也可以抛出构造函数,让用户自己去new,new的时候传参初始化一些配置,效果其实是一样的。

  1. init方法

用户通过调用这个函数来实现在页面上添加水印的效果,所以,这个方法就是用来执行主逻辑的。

在这里插入图片描述

  1. 参数配置

通过init支持用户传递参数过来。

这个就很简单了,根据用户传过来的参数,来执行主逻辑。比如这里的水印内容、颜色、倾斜角度等等,都支持用户自定义配置。不传就用默认值,传了就用用户传过来的参数实现最终效果。
在这里插入图片描述

六、打包

在刚刚第四点中,我们已经提到了打包相关的rollup配置,下图中就是打包流程。执行对应命令,打出最终的插件文件。
在这里插入图片描述

至此,距离成功就已经很接近了,只需要把打包生成的文件发布到npm上,别人就能用你写的插件了!!!如果不太熟悉发布流程,可以参考下篇文章~

如何将自己的插件发布到npm上 / 发布到公司npm源上

文中插件源码获取:https://github.com/zttop/watermark-h5#readme

相关文章:

如何编写一个 npm 插件?

提到写 npm 插件,很多没搞过的可能第一感觉觉得很难,无从下手,其实不然。 我们甚至写个简单的 console.log(hello word),都是可以当成一个插件发布上去的。 其实无从下手的主要难点还是在于你的具体要做的功能逻辑,这…...

mapstruct- 让VO,DTO,ENTITY转换更加便捷

mapstruct- 让VO,DTO,ENTITY转换更加便捷 1. 简介 MapStruct是一个代码生成器,简化了不同的Java Bean之间映射的处理,所谓映射指的就是从一个实体变化成一个实体。例如我们在实际开发中,DAO层的实体和一些数据传输对…...

IAR警告抑制及还原

工作中需要临时抑制 警告 Pa084,源代码如下: sy_errno_t sy_memset_s(void *dest, sy_rsize_t dmax, int value, sy_rsize_t n) { sy_errno_t err; if (dest NULL) { return SY_ESNULLP; } if (dmax > SY_RSIZE…...

工厂模式(Factory Pattern)

1.什么是工厂模式 定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行。 2.工厂模式的作用 实现创建者和调用者的分离 3.工厂模式的分类 简单工厂模式工厂方法模式抽象工厂模式 4.工厂模式的优缺点 优…...

JavaScript语法学习--《JavaScript编程全解》

《JavaScript编程全解》 JavaScript琐碎基础 0.前言 1.RN: react native是Facebook于2015年4月开源的跨平台移动应用开发框架,是Facebook早先开源的JS框架 React 在原生移动应用平台的衍生产物,支持iOS和安卓两大平台。 2.ts与js js:是弱…...

linux安装极狐gitlab

1. 官网寻找安装方式 不管我们使用任何软件,最靠谱的方式就是查看官方文档。gitlab提供了相应的安装文档,并且有对应的中文文档。地址如下: https://gitlab.cn/install/ 我在这里以CentOS作为安装示例,大家可根据自己的需要选择…...

软考高级信息系统项目管理(高项)原创论文——人力资源管理

人力资源管理 某市某国有装备制造公司智能安防信息管控平台项目是在公司推进企业信息化进程和实现企业可持续发展的背景下于2016年8月提出来的,我公司积极应标并最终顺利中标,而我有幸被任命为项目经理,担任起该项目的管理工作。该项目投资金额为530万元,其中软件部分为360…...

Java Lambda表达式 匿名内部类 函数式接口(FunctionalInterface)

Java Lambda表达式定义背景示例匿名类实现Lambda表达式实现对比匿名类和Lambda实现Lambda表达式(调用)说明Lambda表达式的语法Java 1.8 新特性:函数式接口jdk 1.8 自带的函数式接口 (举例)定义 参考Oracle官网&#x…...

javaEE 初阶 — 流量控制与拥塞控制

文章目录1. 流量控制2. 拥塞控制TCP 工作机制:确认应答机制 超时重传机制 连接管理机制 滑动窗口 1. 流量控制 流量控制是一种干扰发送的窗口大小的机制,滑动窗口,窗口越大,传输的效率就越高(一份时间,…...

HTML自主学习 - 2

一、表格 基本语法 <table><tr><td>单元格内容1</td><td>单元格内容2</td><td>单元格内容3</td></tr></table> 1、<table> </table>标签用于定义表格 2、<tr> </tr>标签用于定义表格的…...

【转载】通过HAL库实现MODBUS从机程序编写与调试-----STM32CubeMX操作篇

通过HAL库实现MODBUS从机程序编写与调试-----STM32CubeMX操作篇[【STM32】RS485 Modbus协议 采集传感器数据](https://blog.csdn.net/qq_33033059/article/details/106935583)基于STM32的ModbusRtu通信--ModbusRtu协议(一)基于STM32的ModbusRtu通信--终极Demo设计(二)STM32RS48…...

【C++】string类(上)

文章目录1.为什么要学习string类2.标准库中的string类1.string分类2.string类对象的常见构造1.string3. string类对象的容量操作1.size2.capacity3.reserve4.resize扩容初始化删除数据4. string类对象的修改操作1.push_back2.append3.operator1.为什么要学习string类 c语言的字…...

Java泛型

文章目录一、泛型介绍1. 背景2. 概念3. 好处二、泛型声明泛型类型符号泛型声明方式三、类型擦除1. 什么是类型擦除桥接方法2. 为何需要类型擦除3. 类型信息并未完全擦除四、泛型使用1. 泛型类2. 泛型接口3. 泛型方法五、泛型扩展1. 泛型的上下边界泛型的上边界泛型的下边界2. 泛…...

07 分布式事务Seata使用(2)

1、Seata是什么 Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。AT模式是阿里首推的模式,阿里云上有商用版本的GTS&#x…...

c++练习题5

5.在C语言中&#xff0c;程序运行期间&#xff0c;其值不能被改变的量叫 常量 。 6.符号常量是指用一个符号名代表一个常量。 7&#xff0e;整型常量和浮点型常量也称为 数值常量 &#xff0c;它们有正负之分。 9&#xff0e;在C中&#xff0c;变量是 其值可以改变的量 。 …...

Python 高级编程之正则表达式(八)

文章目录一、概述二、正则表达式语法1&#xff09;字符匹配2&#xff09;字符集合3&#xff09;定位符4&#xff09;分组1、定义分组2、引用分组3、命名分组三、Python 的 re 模块1&#xff09;re.match() 方法2&#xff09;re.search() 方法3&#xff09;re.match() 与 re.sea…...

pynrrd常用操作解析

目录依赖安装官方文档常用操作1. 读部分nrrd.read()nrrd.read_header()nrrd.read_data()2. 写部分nrrd.write()依赖安装 pip install pynrrd官方文档 https://pynrrd.readthedocs.io/en/stable/ 常用操作 1. 读部分 nrrd.read() nrrdpath "your nrrd file path"…...

数据结构:链表基础OJ练习+带头双向循环链表的实现

目录 一.leetcode剑指 Offer II 027. 回文链表 1.问题描述 2.问题分析与求解 (1) 快慢指针法定位链表的中间节点 (2) 将链表后半部分进行反转 附:递归法反转链表 (3) 双指针法判断链表是否回文 二.带头双向循环链表的实现 1.头文件 2.节点内存申请接口和链表初始化接口…...

计算机视觉方向地理空间遥感图像数据集汇总

文章目录1.DSTL卫星图像数据集/Kaggle竞赛2.Swimming Pool and Car Detection/Kaggle竞赛3.SpaceNet Challenge 3数据集4.RarePlanes数据集5.BigEarthNet数据集6.NWPU VHR-10数据集7.UC Merced Land-Use数据集8.Inria Aerial Image Labeling数据集9.RSOD数据集1.DSTL卫星图像数…...

信息系统项目管理师真题精选(一)

1.信息系统的&#xff08; &#xff09;决定了系统可以被外部环境识别&#xff0c;外部环境或者其他系统可以按照预定的方法使用系统的功能或者影响系统的行为。A.可嵌套性B.稳定性C.开放性D.健壮性2、在实际的生产环境中&#xff0c;&#xff08; &#xff09;能使底层物理硬件…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

华为OD机试-食堂供餐-二分法

import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

什么是EULA和DPA

文章目录 EULA&#xff08;End User License Agreement&#xff09;DPA&#xff08;Data Protection Agreement&#xff09;一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA&#xff08;End User License Agreement&#xff09; 定义&#xff1a; EULA即…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中&#xff0c;UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

【7色560页】职场可视化逻辑图高级数据分析PPT模版

7种色调职场工作汇报PPT&#xff0c;橙蓝、黑红、红蓝、蓝橙灰、浅蓝、浅绿、深蓝七种色调模版 【7色560页】职场可视化逻辑图高级数据分析PPT模版&#xff1a;职场可视化逻辑图分析PPT模版https://pan.quark.cn/s/78aeabbd92d1...