您的浏览器版本过低,为保证更佳的浏览体验,请点击更新高版本浏览器

以后再说X
NEWS

新闻与文章

新闻与文章

??rollup实战(三)之从开源角度去优化一个组件库

作者:佚名 发布时间:2024-06-04 17:42:43点击:

这是一个系列专栏,将会更新一系列rollup的实战内容,主要围绕着用rollup构建组件库、构建测试环境、搭建单元测试、构建过程的再优化等内容

本篇文章曾用名:《从开源角度去思考,如何优化一个组件库》

承接上文,我们用 rollup 搭建了一个组件库 ,但还有些需要优化的地方:

  1. 构建速度不够快
  2. 构建的产物只有 esm 模块,没有 umd 模块,iife 模块

本篇文章内容是基于上篇文章的内容,所以了解上篇文章的内容会对阅读更有帮助

传送门:rollup实战(二)之用vite搭建rollup组件库的开发环境

构建产物准备了三种模块,每种模块都有它的作用:

  1. esm 用来支持 esmodule 环境的, 在大多数的开发环境,都是 esmodule,并且 esm 模式支持 tree shaking。所以 esm 是必要的
  2. umd 模块,支持三种模式的引入,一种是 commonjs,一种是 script,还有一种是 amd; 对于 commonjs 在一些 node 环境中是必要的。script 的场景就是在消费端将 external 的时候,就需要用 script 导入了。amd 的场景我还没遇到过

对于 commonjs,我还没有遇到要用 commojs 来开发前端页面的,但是很多库都支持,咱也不能落后不是。 可能一些构建工具在引入库的时候就是 commonjs? 不过对于 script,我倒认为需求场景比较多

  1. iife 模块,iife 模块也是 script 导入使用,但相较于 umd,我更倾向于认为 iife是适配低版本浏览器,只支持 es5,甚至更低的那种。在 script 引入组件库的依赖(ps: react, reactd-dom),然后引入组件库,就可以直接使用。要做到这一点,就需要在 iife 的构建产物中包含所有的 es6 语法的 polyfill。

下面开始

因为需要用到三种模块的构建,所以为了项目结构清晰,需要将不同模块的构建配置文件分开。

创建一个 config 文件夹,并且在里面创建三个 rollup 配置文件
image.png
由于不同配置文件的插件配置是高度重合的,所以单独列出一个文件处理插件,减少代码的重复性


首先准备一个基础的 basePlugins,里面有各个模块都需要的基础功能,

  • , 解析第三方依赖
  • , 解析 commonjs 模块
  • ,解析各种 css 文件格式,其中的参数表示将组件库的 css 样式都提取出来放到一个文件中
  • ,解析各种图片格式,将图片转换为 base64 格式

准备 esm 的插件


构建 esm 模块,编译插件需要处理 ts 和 react 代码,上篇文章中是用处理 ts 代码,用处理 react 代码,输出的最后结果是 es6 代码。

这份工作完全可以交给 esbuild 来做,esbuild 可以同时处理 ts 和 react 代码,而且速度还一个数量级
image.png

在代码编译, esbuild 相较于 webpack,babel 会快很多

nodeExternals 是用来排除所有的所有的第三方依赖的,这样组件库的构建产物体积就会足够的小

准备 umd 模块


umd 模块相比于 esm 模块,有个不同的地方--esbuild 的参数。这个参数的作用是使构建之后的 react 组件生成 reactElement 函数是 ,而不是 中的函数。
image.png

这是 umd 构建产物 -- Input 组件 的截图

这样做的目的是用 script 引入的时候,可以少引入一个的包

使用了这种设置,是不是需要在组件中显示引入 变量呢?答案是:

准备 iife 模块


准备 iife 模块时,不需要将所有的第三方依赖都 external 掉,需要 external 的依赖会在 rollup.external 配置中单独列出来,这也是为了减少 script 引入产物的考量。所以这里拿掉了插件

因为 esbuild 并不能很好支持 es5 代码,所以,还单独加了一个 babel 插件,目的是将 es6 代码转译成 es5。其中的一些配置需要我们注意

  • 一个 targets,表示我们需要支持的浏览器数量,
  • 还有一个是 extensions,用来告诉 bable 插件,你需要它处理哪些文件。它默认是没有 ts、tsx 后缀的,所以我们额外添加。(这是坑,需要特别注意)
  • babelHelpers 设置成 inline, 目的将 polyfill 代码都打包进构建产物中,而不是向 runtime 一样引入其中。虽然会导致构建产物增加,不过这是没有办法的事情

其实要实现这个目的,其实是个更好的选择,但我用了这个值,构建就会报错,这是为什么: image.png

他们的区别在于 inline 会在构建产物每个文件都放一份 polyfill,而 bundle 对构建产物的所有文件都只有一个 polyfill。所以inline 模式会比 bundle 的构建产物体积更大。

不过,其实对我也没有影响,因为我构建产物只有一个文件呀

到此,文件也就准备好了:



这是 esm 模块的配置文件,内容很简单:


入口时 src 中的 , 输出目录是文件夹下面的文件夹。格式是 esm,生成 sourcemap,的意思是编译不打包,构建产物仍然是按照开发的目录结构
image.png

这是 umd 模块的配置文件:


入口和 esm 模块一样,出口是 dist 文件夹下面的 umd 文件夹。umd 还需要给出 script 场景下的全局变量名(取的是 rollup-build 首字母)

其中 globals 的配置目的是告诉 rollup,组件库中引入的 react,react-dom,在 script 场景中,它们的全局变量名是什么。这个变量名不能是自定义的,要看具体的 react umd 格式文件中是什么

那 react 举个例子:

先找到 ract 中 umd 格式的文件
image.png
image.png
红圈圈出来的位置,就是浏览器环境下的定义,给 global 上赋值了一个 React 属性,所以 react 库在 script 环境下的全局变量名称,就是

红圈上面两行,分别是 commonjs 环境,和 AMD 环境,这就是为什么 umd 可以支持三种环境的原因所在了

每 external 一个库,就要在 globals 中专门列出来一个,万一依赖库有十多个,那就太麻烦了。有没有一个库是专门维护这样一个映射关系的?

这是 iife 模块的配置文件:


相同的地方就不讲了,重点关注和其他模块配置不同的地方

  • format 要改成 iife
  • 输出路径,是在目录下面
  • 要额外地写出要 external 哪些库。原因之前提到过,减少 script 场景下需要额外引入的依赖,所以只将消费端大概率也会 external 的库,external 出去

到此,所有模块的配置文件都准备好了,下面准备 package.json


这个配置是面向消费端的,配置了不同模块的入口。如果 commonjs 模块引入,node 就会返回 umd 下面的文件,如果是 esmodule 模块引入,node 就会返回 es 下面的文件。

下面来添加构建的 npm 脚本


当执行,就会同时执行三种模块的构建,

与不相同,是串行执行,用来连接两个命令,如果前面的命令执行失败,就会阻塞后面的命令。是并行执行,也是连接两个命令,但前后命令不会相互影响

不同模块的构建并没有前后关系,所以这里用并行执行

其中,还有个 prebuild 的命令,其会在之前执行。prebuild 内容中,首先是删除 dist 目录,然后执行 tsc,用来生成 ts 的类型文件,还兼有类型检查的功能。如果 ts 类型报错,就会停止构建功能。

当然,报错停止构建后,类型文件也没必要输出了,可以在 tsconfig 中加上,就可以优化的实现这一点了。

构建脚本也准备好了,下面来执行下看看吧!
image.png
两个细节:

  1. 可以看到 log 是交替出现了,印证了构建过程是并行执行的
  2. iife 模块构建的时间是最长的,因为用到了 babel 对 es 代码降级

对比下 umd 和 iife 构建后的组件代码:
image.png
image.png
可以看到 iife 中函数被转换为了 function 形式,不是箭头函数

rollup 支持导出数组类型的配置文件,也就是说可以同时对不同入口,不同模块进行构建

可以这么做:

在 config 文件夹下面创建一个 文件:


文件中将不同模块的配置文件放在一数组中重新导出

package.json 中可以修改 的脚本内容:


其他的构建脚本可以不删除,类似与,,如果有特别需求,可以单独对某个模块进行构建

来执行一下:

可以看到, umd 构建时间显著小于 esm,也许是重用了 esm 模块的构建中间产物吧

这篇文章分享如何对 rollup 构建的组件库进行优化,优化主要两个方向,一个构建速度,构建速度用 esbuild 替代 bable;还有一个是不同模块的构建产物,构建产物分成了三种,分别是 esm, umd, iife。不同模块有其不同的特点,用来适应不同的使用场景

构建产物是准备好了,那怎么对产物进行测试呢?下篇文章来讲吧

rollup 构建相关的另外两篇文章:

  1. rollup实战(一)之rollup搭建组件库
  2. rollup实战(二)之用vite搭建rollup组件库的开发环境
在线客服
联系方式

热线电话

13988889999

上班时间

周一到周五

公司电话

020-88888888

二维码
线

平台注册入口