大概一年前寫了個小小的js插件 remember-scroll,而且分享了一篇文章:用Class寫一個記住用戶離開位置的js插件,是一個純js庫,功能是在用戶再次進入頁面時能自動定位到上一次瀏覽的位置,使用webpack+babel打包,裏面的webpack和babel的配置至今看來也算是很典型的。javascript
前端打包工具備不少——webpack
,gulp
,rollup
等等,網上有不少文章分析它們分別更適合哪些場景,webpack
更適合打包組件庫、應用程序之類的應用,而rollup
更適合打包純js的類庫。所以筆者一直有想法嘗試將 remember-scroll 的打包工具由webpack
更換爲rollup
,從實際應用的角度來對比一下二者的區別。html
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-resolve
讓 rollup
可以識別node_modules的第三方模塊。@rollup/plugin-commonjs
將 CommonJS 的模塊轉換爲 ES2015 供 rollup
處理。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 }
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()) ] }
package.json
打包命令以下:"build": "rollup -c --environment NODE_ENV:production && rollup -c", "dev": "rollup -c --watch",
總之,一切配置都是與以前webpack
版本的同樣,都使用了babel。npm run build
就能夠將資源打包到dist了,接下來咱們對比一下webpack
和rollup
兩個工具打出來的體積有啥區別。vue
筆者特意建了一個同時有rollup和webpack打包出來的資源的分支,你們能夠直接看下github上feature/webpack_rollup
分支的remember-scroll/dist,對比結果以下:java
- | webpack | rollup |
---|---|---|
開發模式大小 | 52.8KB | 19.46KB |
生產打包大小 | 10.3KB | 7.66KB |
生產包gzip後大小 | 4.1KB | 3.4KB |
可見,rollup
打包出來的體積都比webpack
略小一些,經過查看打包出來的代碼,webpack打包出來的文件裏面有不少__webpack_require__
工具函數的定義,可讀性也不好,而rollup打包出來的js會簡單一點。node
項目的 master分支已經改成使用rollup進行構建, feature/webpack分支保留了以前webpack的配置,感興趣的同窗能夠去github上詳細瞭解下。
不得不說,從打包體積上來看,使用rollup
構建無疑是更適合的。webpack
筆者以前遇到過一個問題是package.json
的main
到底應該是指向構建後的開發版本仍是生產版本呢?git
關於package.json中main字段的指向問題這篇文章給了答案:main應該指向開發版本。github
這裏會有一個疑問:引用開發版本的包體積很大,豈不是讓個人應用打包上線版本很大?web
爲了驗證上面 package.json 的main
指向開發或生產版本有什麼不一樣,筆者這裏直接實戰作個對比。
使用VueCli v4.5.9 新建一個vue項目,而後在App.vue
引入不一樣工具打包而成的remember-scroll
,再npm run build
打包該vue項目,對比打包出來chunk-vendors.[hash].js
的體積。
引入的npm包默認會打包進chunk-vendors
,app.js
的增量體積都是同樣的就不做對比了。
- | vue打包 | webpack開發版(52.8KB) | webpack生產版(10.3KB) | rollup開發版(19.46KB,推薦) | rollup生產版(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指向開發版仍是生產版,gzip後幾乎一致,但webpack
打包出來的,main指向開發版時體積會相差很是大。
因此使用webpack
打包的插件,通常都是會根據NODE_ENV
來加載對應的包,NODE_ENV === 'production'
時指向壓縮後的生產版本。好比像下面這樣,在根目錄新建一個index.js
,package.json
的main
指向該文件,而後在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
會更合適一點。
固然,rollup
和webpack
都是做爲構建工具,它們都有着各自的優點和各自的使用場景,利用好它們的優勢就能夠了。