哈喽,大家好,我是 SuperYing。今天我们来聊聊 Rollup 插件开发,整点代码,小试牛刀。

不知道大家是否了解过 Rollup 插件相关的东西,感兴趣的话可以到 Rollup 官网 瞅瞅。

简单点理解,Rollup 的插件就是一个函数,返回值是一个对象,这个对象需要包括 Rollup 规定的属性编译 hooks输出 hooks 等。这部分规定的内容都可以在官网的 plugin-development 部分找到,我就不多赘述了哈。Rollup 插件可以实现诸如在打包前传输代码,在 node_modules 文件夹中查找第三方模块等功能

最近在做一个远程加载组件库的小玩意,为什么要整它呢?现在比较流程的使用组件库方式就是 npm 模块,但是这种方式需要先将框架代码下载到本地,然后在工程中引用。那么也就是说,我自己开发的组件库,要经过 【打包 - 发布 - 卸载旧版本 - 安装新版本】这样一系列的操作过程,循环往复,略微有些麻烦。因此呢,就想将组件库的引用改为远程加载,每次组件库升级仅需要发布即可,哈哈哈,理想很丰满…

好啦,废话不多说,开整…

1.创建插件

新增文件 plugins/roll-plugin-remote-ui.js。(不打算将插件单独发布,与远程加载功能放在同一个库中)。
为什么 ts 工程插件要用 js 写插件? 因为要直接在 rolluo.config.js 中使用,而 ts 文件需要经过编译才可用,所以用 js。

2.实现插件

首先我们需要思考一下,远程加载需要什么
1.import 引入
2.请求远程资源,即 http/https
3.export 导出

我想大致就上面那么多吧,那我们就来实现它。

Rollup 提供一个 build hookresolveId,我们可以通过该 hook 定义一个解析器,在该解析器中捕获远程加载的请求地址,然后利用 node 的能力将远程的资源下载到本地,最终将 import 的目标地址指向生成的本地资源。
思路很清晰,是不是,但是有一个问题,我们怎么判断当前 import 的是资源是需要远程加载呢?判断 sourceimport 语句中的导入对象地址,如 import foo from ‘…/foo.js’,source 就是 ‘…/foo.js’) 是否存在 http/https 吗?可以,但是个人感觉不够精准,因为我们是有上面一套处理流程的,要请求资源并下载到本地的,只要 source 包括 http/https 就一定需要走这一套吗,答案是不一定。这个时候就体现了约定的重要性,我们规定远程加载的组件库地址以 @remote 为前缀,凡是 source 存在该前缀的资源,一律视为远程加载。

下面是插件的代码:

/**
* 远程 UI 资源插件
* 拦截 import,若为远程资源,下载到本地并指向本地资源地址
*/
import path from 'path'
import fs from 'fs-extra'
import request from 'request'export default function remoteUiPlugin() {return {// rollup plugin 约定,需要包含 name 属性,值以 rollup-plugin 开头name: 'rollup-plugin-remote-ui',async resolveId(id) {// 若为 @remote/ 开头,说明引用的是远程资源if (/@remote\//.test(id)) {const [url] = id.match(/https?.*?$/igm) || []if (!url) return idconst timeStamp = new Date().getTime()const finalUrl = `${url}${url.indexOf('?') > -1 ? '&' : '?'}timestamp=${timeStamp}`return await generateLocal(finalUrl)}}}
}// 生成本地资源
function generateLocal(url, localPath = './remote-ui') {const folder = path.resolve(__dirname, localPath)// 同步确认该目录是否存在,若不存在,则创建fs.ensureDirSync(folder)const queryIndex = path.basename(url).indexOf('?')const fileName = path.basename(url).substring(0, queryIndex)const local = path.resolve(folder, `./${fileName}`)return new Promise((resolve, reject) => {const stream = fs.createWriteStream(local)request(url).pipe(stream).on("close", function (err) {if (err) reject(err)// 返回本地资源地址resolve(local)});})
}

好啦,以上就是整个插件的实现代码,很简陋有木有,还有需要需要改进的地方。如果各位大佬有更好的思路欢迎评论区分享哈。

3.应用插件

这一步涉及到 Rollup 配置文件 rollup.config.js,引入插件文件后,在 plugins 配置项下添加即可。
代码如下:

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import { DEFAULT_EXTENSIONS } from '@babel/core';
import rollupTypescript from 'rollup-plugin-typescript2';
import { eslint } from 'rollup-plugin-eslint';
import { terser } from 'rollup-plugin-terser'
import remoteUiPlugin from './plugins/rollup-plugin-remote-ui.js'; // 引入插件
import pkg from './package.json';
import path from 'path'// 环境
const env = process.env.NODE_ENV
const name = 'RemoteUI'
const config = {input: path.join(__dirname, 'src/index.ts'),output: [// umd{name,file: pkg.umd,format: 'umd'},// commomjs{file: pkg.main,format: 'cjs'},// esm{file: pkg.module,format: 'es'}],plugins: [eslint({throwOnError: true, // lint 结果有错误将会抛出异常throwOnWarning: true,include: ['src/*.ts', 'src/**/*.ts'],exclude: ['node_modules/**', 'dist/**', '*.js'],}),resolve(), // so Rollup can find `ms`、commonjs(), // so Rollup can convert `ms` to an ES modulerollupTypescript(),remoteUiPlugin(), // 使用插件babel({// 编译库使用 runtimebabelHelpers: 'runtime',// 只转换源代码,不运行外部依赖exclude: 'node_modules/**',// babel 默认不支持 ts 需要手动添加extensions: [...DEFAULT_EXTENSIONS,'.ts',],}),],external: ['vue']
}
export default config

4.测试插件

到此我们的插件就算是用起来了,我们来写点代码测试一下,瞅瞅效果。
src/index.ts 中添加如下代码:

// 这里的远程地址我实在本地 nginx 部署的组件库,大家自己测试的时候需要改成可用的地址哦
export * from '@remote/http://localhost:9090/dist/bgy-plus/dist/index.full.mjs'

test/test.js 中添加如下代码:

// eslint-disable-next-line @typescript-eslint/no-var-requires
const RemoteUI = require('../dist/index.js')
// RemoteUI 即为最终 import 的组件库对象,我们控制台打印一下其中的 ElButton 组件
console.log('RemoteUI', RemoteUI.ElButton)

打开终端,执行 npm run test关于整个目录结构及 npm script 等,请参考 从0到1搭建 Rollup + TypeScript 模板工程)。

我们可以看到,组件对象正常打印,左侧 plugins 目录中,也生成了本地资源文件。

OK,整完收工!以上便是「 Rollup 插件开发牛刀小试 」的全部内容,感谢阅读。

欢迎各路大佬讨论、批评、指正,共同进步才是硬道理!

Rollup 插件开发牛刀小试相关推荐

  1. JS打包工具rollup——完全入门指南

    因项目需要,最近一直在研究前端打包技术,参照以下文章及rollup官网,通过亲手操练,对rollup有了初步的了解.看到一篇不错的文章,转载记录.感谢作者的无私分享. 原文链接地址:https://s ...

  2. 【Chrome插件开发】ReRes和request-interceptor源码赏析+复现+插件开发完整解决方案

    文章目录 引言 亮点 Chrome插件ReRes源码赏析 Chrome插件request-interceptor background.js源码赏析 技术选型 配置stylelint vscode配置 ...

  3. ATS插件开发中内存泄露问题的解决方法探讨

    接触ATS开发已经有几年了,开发过内核的模块,也从事过插件的开发.内存泄露问题一直是一个困扰大多数ATS开发者的头疼的问题,下面说说我自己的感受和思考.这里这关注ATS插件开发这个话题.源码的exam ...

  4. jQuery插件开发 - 其实很简单

    [前言] jQuery已经被广泛使用,凭借其简洁的API,对DOM强大的操控性,易扩展性越来越受到web开发人员的喜爱,我在社区也发布了很多的jQuery插件,经常有人询问一些技巧,因此干脆写这么一篇 ...

  5. jquery 插件开发的作用域及基础

    2019独角兽企业重金招聘Python工程师标准>>> 之前一直有开发jquery插件的冲动,所以一直想学习如何进行插件开发,最近一个项目需要使用图片上传组件及自动无限下拉组件,百度 ...

  6. Nutch插件开发及发布流程

    2019独角兽企业重金招聘Python工程师标准>>>  一,插件开发流程: 1,Nutch开发客户端环境搭建 2,plugin的源代码则保存在/src/java/org/apach ...

  7. SQL SERVER中ROLLUP的用法

    cube操作符 要使用cube,首先要了解group by 其实cube和rollup区别不太大,只是在基于group by 子句创建和汇总分组的可能的组合上有一定差别, cube将返回的更多的可能组 ...

  8. oralce rollup 小计合计_总计与小计–WITH ROLLUP

    rollup:汇总 在GROUP后加WITH ROLLUP来实现总计与小计,它会对每次分组的结果进行ROLLUP操作,产生汇总的结果,显示在行下. 在显示的时候可用GROUPING来判断当天是数据行还 ...

  9. 深入理解 Mybatis 插件开发

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 作者:风一样的码农 cnblogs.com/chenpi/p/10 ...

  10. 【直播回顾】蚂蚁金服高级开发工程师萧恺:IDEA 插件开发入门教程

    主讲人:萧恺(蚂蚁金服-支付宝事业群-高级开发工程师) 本名:肖汉松 讲师介绍: 热爱阅读,喜欢挑战,热衷尝试新的技术,关注技术背后的原理. 关注领域:Java 服务端开发,分布式系统 关注语言:Ja ...

最新文章

  1. WannaCry 不相信眼泪 它需要你的安全防御与响应能力
  2. Python Web实战:Python+Django+MySQL实现基于Web版的增删改查
  3. Xamarin.FormsShell基础教程(2)创建Shell解决方案
  4. 西南石油大学计算机二级成绩查询,西南石油大学本科学生成绩自助查询打印终端管理办法...
  5. 【Python】牛客的输入输出到底怎么整??
  6. 基于Web用户控件的Portal
  7. [JavaWeb-JavaScript]JavaScript流程控制语句
  8. (Docker实战) 第三篇:配置_开发环境
  9. PyTorch JIT与TorchScript
  10. Spring对象绑定与类型转换
  11. html5 Canvas 标签介绍
  12. Skype for Business Server 2015-12-WAP-发布-1-前端服务器-OWAS01
  13. Linux网络编程---htons函数的使用
  14. gpt2 代码自动补全_如果您认为GPT-3使编码器过时,则您可能不编写代码
  15. GoAhead服务器编程
  16. 关于安装Turn服务器:coturn,TurnServer,Restund,reTurnServer
  17. 异步操作及定时任务框架quzrtz在donet平台的使用
  18. 获取基金数据python库_PYTHON爬取基金数据及基金筛选
  19. golang: grpc: received message larger than max
  20. 2021金融科技领域最具商业合作价值企业盘点

热门文章

  1. python自学课堂_python自学——列表
  2. Android系统预装Chrome并自定义主页
  3. QQ游戏自动登录器V4.0
  4. PCB多层板设计总结-层的分布设置
  5. 2018年计算机网络统考考试试题,2018年下半年网络工程师考试上午试题及答案
  6. msvcp140.dll丢失的解决方法_msvcp140.dll丢失怎样修复win10
  7. 无线桥接后无法访问服务器,无线桥接后不能登录副路由器ip地址的解决方法
  8. html5版堆糖,堆糖(Duitang)
  9. 使用github免费搭建个人博客后的写作及上传说明
  10. 智商情商哪个重要_智商or情商 哪个对孩子更重要