真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

基于rollup的組件庫打包體積優(yōu)化小結

背景

創(chuàng)新互聯(lián)堅持“要么做到,要么別承諾”的工作理念,服務領域包括:網(wǎng)站制作、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務,滿足客戶于互聯(lián)網(wǎng)時代的寶興網(wǎng)站設計、移動媒體設計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡建設合作伙伴!

前段時間對公司內(nèi)部的組件庫(類似element-ui)做了打包體積優(yōu)化,現(xiàn)在抽點時間記錄下。以前也做過構建速度的優(yōu)化,具體可以看組件庫的webpack構建速度優(yōu)化

一些存在的問題

最開始打包是基于webpack的,在按需加載上存在的體積冗余會比較大,如:

  1. webpack打包特有的模塊加載器函數(shù),這部分其實有些多余,最好去掉
  2. 使用babel轉(zhuǎn)碼時,babel帶來的helper函數(shù)全部是內(nèi)聯(lián)狀態(tài),需要轉(zhuǎn)成importrequire來引入
  3. 使用transform-rumtime對一些新特性添加polyfill,也是內(nèi)聯(lián)狀態(tài),需要轉(zhuǎn)成importrequire來引入
  4. vue-loader帶來的額外代碼,如normalizeComponent,不做處理也是內(nèi)聯(lián)
  5. transform-vue-jsx帶來的額外函數(shù)引入,如mergeJSXProps,不做處理也是內(nèi)聯(lián)

以上幾個問題,如果只是一份代碼,那不會有太大問題,但是如果是按需加載,用戶一旦引入多個組件,以上的代碼就會出現(xiàn)多份,帶來嚴重的影響

import { Button, Icon } from 'gs-ui'

以上代碼會轉(zhuǎn)成

import Button from 'gs-ui/lib/button.js'
import Icon from 'gs-ui/lib/icon.js'

這樣,就會出現(xiàn)多份相同的helper函數(shù)代碼,多份webpack的模塊加載器函數(shù),而且還不好去重

尋找解決方案

討論過后主要有以下幾種選擇

采用后編譯

我們也認同這種方案,采用后編譯可以解決上面的各種問題,也有組件庫是這樣做的,比如cube-ui,但是這樣有些不方便,因為用戶需要設置各種alias,還要保證好各種編譯環(huán)境,如jsx,而且未來可能會引入flow,會更加不方便,所以暫時不考慮

使用rollup打包,設置external(當然webpack也可以)外聯(lián)helper函數(shù)

使用rollup打包,可以直接解決問題1和問題4,設置external可以解決transform-runtime等帶來的helper,這取決于相關插件實現(xiàn)時是不是通過importrequire來添加helper的,如果是直接copy的話,那就還得另找辦法。最后決定就這種方案進行嘗試

使用rollup對打包進行重構

使用rollup打包可能某些習慣和webpack有些出入,在這里很多事需要引入插件來完成,比如引入node_modules中的模塊的話,需要加入rollup-plugin-node-resolve,加載commonjs模塊需要引入rollup-plugin-commonjs等等。另外還有些比較麻煩的,比如經(jīng)常會這樣寫

import xx from './xx-folder'

然后希望模塊打包器可以識別成

import xx from './xx-folder/index.js'

rollup里還是需要用插件來完成這件事,找到的插件都沒能滿足各種需求,比如還需要對alias也能識別然后加上index.js,最后還是需要自己實現(xiàn)這個插件

基本的rollup配置應該差不多是這樣的

{
 output: {
  format: 'es',
  // file: xx,
  // paths: 
 },
 input: 'xxx',
 plugins: [
  vue({
   compileTemplate: true,
   htmlMinifier: {
    customAttrSurround: [[/@/, new RegExp('')], [/:/, new RegExp('')]],
    collapseWhitespace: true,
    removeComments: true
   }
  }),
  babel({
   ...babelrc({
    addModuleOptions: false,
    addExternalHelpersPlugin: false
   }),
   exclude: 'node_modules/**',
   runtimeHelpers: true
  }),
  localResolve({
   components: path.resolve(__dirname, '../components')
  }),
  alias({
   components: path.resolve(__dirname, '../components'),
   resolve: ['.js', '.vue']
  }),
  replace({
   'process.env.NODE_ENV': JSON.stringify('development')
  })
 ],
 // external
}

這里采用的rollup-plugin-vue的版本是v3.0.0,不采用v4,因為打包出來的體積更小,功能完全滿足組件庫需要。因為會存在各種約定,比如組件肯定是存在render函數(shù)(不一定指的就是手寫renderjsx,只是不會有在js中使用template這種情況,這樣的好處是可以使用runtime-onlyvue),組件肯定不存在style部分等等。

babel的配置上基本不會有改變,只是rollup-plugin-babel加上了runtimeHelpers,用來開啟transform-runtme的。可能你會覺得為了更精簡體積,應該去掉transform-runtime,這點我持保留意見,這里使用transform-runtime的主要作用是為了接管babel-helpers,因為這個babel-helpers無法被external。另外整個組件庫用到的babel-runtime其實也不多,主要是類似Object.assign這樣的函數(shù),像這些函數(shù),使用的話還是需要加上transform-runtime的,或者需要自己實現(xiàn),感覺沒什么必要。類似Array.prototype.includes這種無法被transform-runtime處理的還是會避免使用的

localResolve是自己實現(xiàn)的插件,用來添加index.js,并且能支持alias,

alias插件用來添加alias,并且需要設置后綴

replace插件用來替換一些環(huán)境變量,比如開發(fā)環(huán)境會有錯誤提示,生成環(huán)境不會有,這里展示的是開發(fā)環(huán)境的配置。

配置external

所有優(yōu)化的關鍵在于external上,除了最基本的vue需要external外,還有比如Button組件內(nèi)部依賴了Icon組件,那是需要把Icon組件external

// Button 組件
import Icom from 'components/icon'

其實就是所有的組件和共用的util函數(shù)都需要external,當然這里本來就存在了,不是本次優(yōu)化要做的

主要要處理的是babel-helperhelper函數(shù),但是這里不能做到,我也沒有去了解babel是如何對這塊進行處理的,最后還是需要transform-runtime來接管它。

rollupexternal配置是支持函數(shù)類型的,大概看tranform-runtime這個插件源碼可以找到addImport這些方法,可以知道polyfill是通過import來引入的,可以被external,所以只需要在rollup配置的external添加上類似函數(shù)就可以達到我們想要的效果

{
 external (id) {
  // 對babel-runtime進行external
  return /^babel-runtime/.test(id) // 當然別忘了還有很多 比如vue等等,這里就不寫了
 }
}

這里就可以解決問題2和問題3

另外問題5,這個是如何來的呢,比如在寫jsx時,可能會這樣寫

// xx組件
export default {
 render () {
  return (
   
{/* other */}
) } }

在某個組件中依賴了另一個組件,考慮到擴展性,是支持對另一個組件進行props設置的,所以經(jīng)常會這樣寫,在template中的話就類似于v-bind="tolltipProps"

這個時候transform-vue-jsx插件是會引入一個helper函數(shù)的,也就是babel-helper-vue-jsx-merge-props,大概看看transform-vue-jsx源碼也可以得知,這個helper也是import進來的,所以可以把external改成

{
 external (id) {
  return /^babel/.test(id)
 }
}

這樣就可以做到對所有helper都使用import的形式來引入,而且使用rollup打包后的代碼更可讀,大概長這樣

// Alert組件
import _defineProperty from 'babel-runtime/helpers/defineProperty';
import Icon from 'gs-ui/lib/icon.js';

var Alert = { render: function render() {
  var _class;

  var _vm = this;var _h = _vm.$createElement;var _c = _vm._self._c || _h;return _c('transition', { attrs: { "name": "gs-zoom-in-top" } }, [_vm.show ? _c('div', { class: (_class = { 'gs-alert': true }, _defineProperty(_class, 'gs-alert-' + _vm.type, !!_vm.type), _defineProperty(_class, 'has-desc', _vm.desc || _vm.$slots.desc), _class) }, [_vm.showIcon ? _c('div', { staticClass: "gs-alert-icon", class: { "gs-alert-icon-top": !!_vm.desc } }, [_vm._t("icon", [_c('gs-icon', { attrs: { "name": _vm.icon } })])], 2) : _vm._e(), _vm._v(" "), _c('div', { staticClass: "gs-alert-content" }, [_vm.title || _vm.$slots.default ? _c('div', { staticClass: "gs-alert-title" }, [_vm._t("default", [_vm._v(_vm._s(_vm.title))])], 2) : _vm._e(), _vm._v(" "), _vm.desc || _vm.$slots.desc ? _c('div', { staticClass: "gs-alert-desc" }, [_vm._t("desc", [_vm._v(_vm._s(_vm.desc))])], 2) : _vm._e(), _vm._v(" "), _vm.closable ? _c('div', { staticClass: "gs-alert-close", on: { "click": _vm.close } }, [_vm._t("close", [_vm._v(" " + _vm._s(_vm.closeText) + " "), !_vm.closeText ? _c('gs-icon', { attrs: { "name": "close" } }) : _vm._e()])], 2) : _vm._e()])]) : _vm._e()]);
 }, staticRenderFns: [],
 name: 'GsAlert',
 components: _defineProperty({}, Icon.name, Icon),
 // props
 // data

 // methods
};

/* istanbul ignore next */
Alert.install = function (Vue) {
 Vue.component(Alert.name, Alert);
};

export default Alert;

vue插件把vue組件中的template轉(zhuǎn)成render函數(shù),babel插件做語法轉(zhuǎn)換,因為external的存在,保留了模塊關系,整個代碼看起來很清晰,很舒服,不像webpack,都會添加一個模塊加載函數(shù)...

優(yōu)化后和優(yōu)化前的體積對比

下面的截圖是生產(chǎn)環(huán)境的版本,也就是沒有了代碼提示,也已經(jīng)壓縮混淆后的代碼體積對比
左邊是優(yōu)化前,右邊是優(yōu)化后

基于rollup的組件庫打包體積優(yōu)化小結

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。


當前名稱:基于rollup的組件庫打包體積優(yōu)化小結
轉(zhuǎn)載源于:http://weahome.cn/article/gijeed.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部