当前位置: 首页 > 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

http://www.lryc.cn/news/7810.html

相关文章:

  • mapstruct- 让VO,DTO,ENTITY转换更加便捷
  • IAR警告抑制及还原
  • 工厂模式(Factory Pattern)
  • JavaScript语法学习--《JavaScript编程全解》
  • linux安装极狐gitlab
  • 软考高级信息系统项目管理(高项)原创论文——人力资源管理
  • Java Lambda表达式 匿名内部类 函数式接口(FunctionalInterface)
  • javaEE 初阶 — 流量控制与拥塞控制
  • HTML自主学习 - 2
  • 【转载】通过HAL库实现MODBUS从机程序编写与调试-----STM32CubeMX操作篇
  • 【C++】string类(上)
  • Java泛型
  • 07 分布式事务Seata使用(2)
  • c++练习题5
  • Python 高级编程之正则表达式(八)
  • pynrrd常用操作解析
  • 数据结构:链表基础OJ练习+带头双向循环链表的实现
  • 计算机视觉方向地理空间遥感图像数据集汇总
  • 信息系统项目管理师真题精选(一)
  • 信息系统项目管理师刷题知识点(持续更新)
  • RabbitMq及其他消息队列
  • Toolformer: Language Models Can Teach Themselves to Use Tools
  • 悲观锁与乐观锁
  • LeetCode 25. K 个一组翻转链表
  • 朗润国际期货招商:历次科技风头下巨头的博弈
  • 配置中心Config
  • 【原创】java+jsp+servlet学生信息管理系统(jdbc+ajax+filter+cookie+分页)
  • 链表题目总结 -- 回文链表
  • JAVA集合之List >> Arraylist/LinkedList/Vector结构
  • Linux多进程开发