為什么說rollup比webpack更適合打包庫

前言

大概一年前寫了個(gè)小小的js插件 remember-scroll,并且分享了一篇文章:用Class寫一個(gè)記住用戶離開位置的js插件,是一個(gè)純js庫,功能是在用戶再次進(jìn)入頁面時(shí)能自動定位到上一次瀏覽的位置,使用webpack+babel打包,里面的webpack和babel的配置至今看來也算是很典型的。

前端打包工具有很多——webpack,gulp,rollup等等,網(wǎng)上有很多文章分析它們分別更適合哪些場景,webpack更適合打包組件庫、應(yīng)用程序之類的應(yīng)用,而rollup更適合打包純js的類庫。因此筆者一直有想法嘗試將 remember-scroll 的打包工具由webpack更換為rollup,從實(shí)際應(yīng)用的角度來對比一下兩者的區(qū)別。

從零配置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 的模塊轉(zhuǎn)換為 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 用于避免污染全局函數(shù)(不是必須要用到,但作為類庫最好要加上)。
  • @babel/preset-env 自動根據(jù)目標(biāo)瀏覽器注入相關(guān)的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兩個(gè)工具打出來的體積有啥區(qū)別。

webpack和rollup打包體積對比

筆者特地建了一個(gè)同時(shí)有rollup和webpack打包出來的資源的分支,大家可以直接看下github上feature/webpack_rollup分支的remember-scroll/dist,對比結(jié)果如下:

- webpack rollup
開發(fā)模式大小 52.8KB 19.46KB
生產(chǎn)打包大小 10.3KB 7.66KB
生產(chǎn)包gzip后大小 4.1KB 3.4KB

可見,rollup打包出來的體積都比webpack略小一些,通過查看打包出來的代碼,webpack打包出來的文件里面有很多__webpack_require__工具函數(shù)的定義,可讀性也很差,而rollup打包出來的js會簡單一點(diǎn)。

項(xiàng)目的master分支已經(jīng)改為使用rollup進(jìn)行構(gòu)建,feature/webpack分支保留了之前webpack的配置,感興趣的同學(xué)可以去github上詳細(xì)了解下。

不得不說,從打包體積上來看,使用rollup構(gòu)建無疑是更適合的。

package.json的main指向問題

筆者之前遇到過一個(gè)問題是package.jsonmain到底應(yīng)該是指向構(gòu)建后的開發(fā)版本還是生產(chǎn)版本呢?

關(guān)于package.json中main字段的指向問題這篇文章給了答案:main應(yīng)該指向開發(fā)版本。

這里會有一個(gè)疑問:引用開發(fā)版本的包體積很大,豈不是讓我的應(yīng)用打包上線版本很大?

為了驗(yàn)證上面 package.json 的main指向開發(fā)或生產(chǎn)版本有什么不同,筆者這里直接實(shí)戰(zhàn)做個(gè)對比。

使用VueCli v4.5.9 新建一個(gè)vue項(xiàng)目,然后在App.vue引入不同工具打包而成的remember-scroll,再npm run build打包該vue項(xiàng)目,對比打包出來chunk-vendors.[hash].js的體積。

引入的npm包默認(rèn)會打包進(jìn)chunk-vendors,app.js的增量體積都是一樣的就不作對比了。

- vue打包 引webpack開發(fā)版(52.8KB) webpack生產(chǎn)版(10.3KB) rollup開發(fā)版(19.46KB,推薦) rollup生產(chǎn)版(7.66KB)
Size 89.42 134.97 99.34 97.29 96.96
Gzip 32.04 40.47 34.60 34.52 34.51

可以看到,使用rollup打包的,無論main指向開發(fā)版還是生產(chǎn)版,gzip后幾乎一致,但webpack打包出來的,main指向開發(fā)版時(shí)體積會相差非常大。

所以使用webpack打包的插件,一般都是會根據(jù)NODE_ENV來加載對應(yīng)的包,NODE_ENV === 'production'時(shí)指向壓縮后的生產(chǎn)版本。比如像下面這樣,在根目錄新建一個(gè)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')
}

倘若各位以后要寫一個(gè)用webpack打包的插件,要特別注意這一點(diǎn)。

而如果用rollup打包的,其實(shí)就不用在意這個(gè)細(xì)節(jié)啦,在這個(gè)環(huán)節(jié)rollup又比webpack更香一點(diǎn)哈哈哈。

總結(jié)

通過實(shí)戰(zhàn),功能不變且瀏覽器兼容性一致的情況下,對remember-scroll這個(gè)js庫來說,使用rollup打包確實(shí)比webpack會更合適一些。所以如果我們以后要做技術(shù)選型,對于純js的類庫,選擇使用rollup會更合適一點(diǎn)。

當(dāng)然,rollupwebpack都是作為構(gòu)建工具,它們都有著各自的優(yōu)勢和各自的使用場景,利用好它們的優(yōu)點(diǎn)就可以了。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容