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

54次阅读

共计 3470 个字符,预计需要花费 9 分钟才能阅读完成。

前言

大略一年前写了个小小的 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,比照后果如下:

webpack rollup
开发模式大小 52.8KB 19.46KB
生产打包大小 10.3KB 7.66KB
生产包 gzip 后大小 4.1KB 3.4KB

可见,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 的增量体积都是一样的就不作比照了。
| – | vue 打包 | 引 webpack 开发版(52.8KB) | 引 webpack 生产版(10.3KB) | 引 rollup 开发版(19.46KB, 举荐) | 引 rollup 生产版(7.66KB)|

Size 89.42KB 134.97 99.34 97.29KB 96.96KB
Gzip 32.04KB 40.47 34.60 34.52KB 34.51KB

能够看到,应用 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 都是作为构建工具,它们都有着各自的劣势和各自的应用场景,利用好它们的长处就能够了。

正文完
 0