为什么说 rollup 比 webpack 更适合打包库

用户头像
fengxianqi
关注
发布于: 2020 年 12 月 29 日
为什么说rollup比webpack更适合打包库

前言

大概一年前写了个小小的js插件 remember-scroll,并且分享了一篇文章:用Class写一个记住用户离开位置的js插件,是一个纯js库,功能是在用户再次进入页面时能自动定位到上一次浏览的位置,使用webpack+babel打包,里面的webpack和babel的配置至今看来也算是很典型的。



前端打包工具有很多——webpack,gulp,rollup等等,网上有很多文章分析它们分别更适合哪些场景,**webpack更适合打包组件库、应用程序之类的应用,而rollup更适合打包纯js的类库**。因此笔者一直有想法尝试将 remember-scroll 的打包工具由webpack更换为rollup,从实际应用的角度来对比一下两者的区别。



从零配置rollup

  1. 安装rollup和一些插件

npm i rollup rollup-plugin-uglify rollup-plugin-filesize @rollup/plugin-node-resolve @rollup/plugin-commonjs -D
  • rollup-plugin-uglify 用于压缩混淆打包后的js。

  • rollup-plugin-filesize打包后在控制台显示文件大小。

  • @rollup/plugin-node-resolverollup 能够识别node_modules的第三方模块。

  • @rollup/plugin-commonjs将 CommonJS 的模块转换为 ES2015 供 rollup 处理。

  1. 添加babel

npm i @rollup/plugin-babel @babel/core @babel/plugin-transform-runtime @babel/preset-env core-js@2 -D
  • @rollup/plugin-babel rollup 的babel插件。

  • @babel/core babel核心。

  • @babel/plugin-transform-runtime 用于避免污染全局函数(不是必须要用到,但作为类库最好要加上)。

  • @babel/preset-env 自动根据目标浏览器注入相关的polyfill。

  • core-js polyfill的类库,这里使用的是2.x版本(使用3会增加包的大小)。



根目录下的babel.config.js如下:

const presets = [
[
'@babel/env',
{
useBuiltIns: 'usage',
corejs: { version: 2 }
},
],
]
const plugins = [
'@babel/plugin-transform-runtime'
]
module.exports = { presets, plugins }



  1. 根目录下新建rollup.config.js,全部配置如下:

import filesize from 'rollup-plugin-filesize'
import babel from '@rollup/plugin-babel'
import resolve from '@rollup/plugin-node-resolve'
import { uglify } from 'rollup-plugin-uglify'
import commonjs from '@rollup/plugin-commonjs'
const isProd = process.env.NODE_ENV === 'production'
export default {
input: 'src/index.js',
output: {
file: isProd ? 'dist/remember-scroll.min.js' : 'dist/remember-scroll.js',
format: 'umd',
exports: 'default',
name: 'RememberScroll',
},
plugins: [
resolve(),
commonjs(),
filesize(),
babel({ babelHelpers: 'runtime', exclude: ['node_modules/**'] }),
(isProd && uglify())
]
}
  1. package.json打包命令如下:

"build": "rollup -c --environment NODE_ENV:production && rollup -c",
"dev": "rollup -c --watch",



总之,一切配置都是与之前webpack版本的一样,都使用了babel。npm run build就可以将资源打包到dist了,接下来我们对比一下webpackrollup两个工具打出来的体积有啥区别。



webpack和rollup打包体积对比

笔者特地建了一个同时有rollup和webpack打包出来的资源的分支,大家可以直接看下github上feature/webpack_rollup分支的remember-scroll/dist,对比结果如下:





可见,rollup打包出来的体积都比webpack略小一些,通过查看打包出来的代码,webpack打包出来的文件里面有很多__webpack_require__工具函数的定义,可读性也很差,而rollup打包出来的js会简单一点。



项目的master分支已经改为使用rollup进行构建,feature/webpack分支保留了之前webpack的配置,感兴趣的同学可以去github上详细了解下。



不得不说,从打包体积上来看,使用rollup构建无疑是更适合的。



package.json的main指向问题

笔者之前遇到过一个问题是package.jsonmain到底应该是指向构建后的开发版本还是生产版本呢?



关于package.json中main字段的指向问题 这篇文章给了答案:main应该指向开发版本。



这里会有一个疑问:引用开发版本的包体积很大,岂不是让我的应用打包上线版本很大?



为了验证上面 package.json 的main指向开发或生产版本有什么不同,笔者这里直接实战做个对比。



使用VueCli v4.5.9 新建一个vue项目,然后在App.vue引入不同工具打包而成的remember-scroll,再npm run build打包该vue项目,对比打包出来chunk-vendors.[hash].js的体积。



引入的npm包默认会打包进chunk-vendorsapp.js的增量体积都是一样的就不作对比了。





可以看到,使用rollup打包的,无论main指向开发版还是生产版,gzip后几乎一致,但webpack打包出来的,main指向开发版时体积会相差非常大。



所以使用webpack打包的插件,一般都是会根据NODE_ENV来加载对应的包,NODE_ENV === 'production'时指向压缩后的生产版本。比如像下面这样,在根目录新建一个index.jspackage.jsonmain指向该文件,然后在js中写上:



if (process.env.NODE_ENV === 'production') {
module.exports = require('./dist/remember-scroll.min.js')
} else {
module.exports = require('./dist/remember-scroll.js')
}



倘若各位以后要写一个用webpack打包的插件,要特别注意这一点。



而如果用rollup打包的,其实就不用在意这个细节啦,在这个环节rollup又比webpack更香一点哈哈哈。



总结

通过实战,功能不变且浏览器兼容性一致的情况下,对remember-scroll这个js库来说,使用rollup打包确实比webpack会更合适一些。所以如果我们以后要做技术选型,对于纯js的类库,选择使用rollup会更合适一点。



当然,rollupwebpack都是作为构建工具,它们都有着各自的优势和各自的使用场景,利用好它们的优点就可以了。



发布于: 2020 年 12 月 29 日阅读数: 9
用户头像

fengxianqi

关注

https://github.com/fengxianqi 2020.07.20 加入

前端同学

评论

发布
暂无评论
为什么说rollup比webpack更适合打包库