vue異步組件 懶加載& webpack按需加載——性能優(yōu)化

利用webpack對代碼進(jìn)行分割是懶加載的前提,懶加載就是異步調(diào)用組件,需要時(shí)候才下載(按需加載)。

為什么需要懶加載?
在單頁應(yīng)用中,如果沒有應(yīng)用懶加載,運(yùn)用webpack打包后的文件將會異常的大,造成進(jìn)入首頁時(shí),需要加載的內(nèi)容過多,延時(shí)過長,不利于用戶體驗(yàn),而運(yùn)用懶加載則可以將頁面進(jìn)行劃分,需要的時(shí)候加載頁面,可以有效的分擔(dān)首頁所承擔(dān)的加載壓力,減少首頁加載用時(shí)。

vue開發(fā)過程中,我們會做出特別多特別多的組件,包括login,header,footer,main等等。
這樣使整個(gè)網(wǎng)站看起來就十分的龐大,當(dāng)我們在打開網(wǎng)頁的時(shí)候,突然一下子把這些所有的組件加載上來,這么多的請求全部同時(shí)開始請求,勢必會造成網(wǎng)頁打開很慢,使客戶得到的是非常差勁的體驗(yàn)。

因此,vue為我們專門設(shè)立了異步組件,通過異步組件,我們可以得到兩點(diǎn)好處:
1、 用不到的組件不會加載,因此網(wǎng)頁打開速度會很快,當(dāng)你用到這個(gè)組件的時(shí)候,才會通過異步請求進(jìn)行加載;
2、 緩存組件,通過異步加載的組件會緩存起來,當(dāng)你下一次再用到這個(gè)組件時(shí),絲毫不會有任何的疑遲,組件很快會從緩存中加載出來。

異步組件=原理同webpack的按需加載
好處:
1)按需加載,可以節(jié)省首次加載時(shí)間,提高速度,性能優(yōu)化
2)第一次加載完成會緩存

異步組件的描述:

Vue允許將組件定義為一個(gè)異步解析(加載)組件定義的工廠函數(shù),即Vue只在實(shí)際需要渲染組件時(shí),才會觸發(fā)調(diào)用工廠函數(shù),并且將結(jié)果緩存起來,用于將來再次渲染。

!!!ps:要使用異步組件,一個(gè)比較推薦的方式就是配合webpack代碼分離功能。

例子:(全局|局部)
法一:結(jié)合webpack

//1)全局:
 Vue.component('component-name',function(resolve){
 //require 語法告訴 webpack自動將編譯后的代碼分割成不同的塊
 //這些塊將通過 Ajax 請求自動下載
   require(['./my-async-componnet'],resolve)
 })
 //注冊全局組件名,但只有一個(gè)名字,沒有實(shí)體,相當(dāng)于空的
//當(dāng)需要這個(gè)組件時(shí),調(diào)用上面的工廠函數(shù),觸發(fā)webpack的異步加載模塊方法
//然后異步請求一個(gè)模塊,請求成功后,這個(gè)模塊內(nèi)容即為組件實(shí)體部分,并對應(yīng)地方渲染,加載內(nèi)容也緩存下來。

//2)局部
 new Vue({
   components: {
        'component-name':function(resolve) {
           require(['./my-component'], resolve)
        }
   }
 })

法二:通過webpack2+es2015返回一個(gè)promise

//1)全局:
Vue.component('component-name',
 ()=> import('./my-async-componnet')
 )
//2) 局部:
 new Vue({
   components: {
       'component-name': () =>  import('./my-async-componnet')
   }
 })

高級異步組件(即處理加載狀態(tài))
工廠對象可以返回一個(gè)對象,對象里面的一些配置參數(shù)

    const asyncComponent = () => ({
    // 需要加載的組件 (應(yīng)該是一個(gè) `Promise` 對象)
    component: import('./my-async-componnet'),
    //異步加載時(shí)使用的組件(加載中的效果)
    loading: loadingComponent,
    //加載失敗時(shí)使用的組件
    error: ErrorComponent,
    //展示加載中組件的延時(shí)時(shí)間,默認(rèn)200毫秒
    delay: 200,
    //超時(shí)時(shí)間,超過該時(shí)間顯示加載失敗的組件
    timeout: 3000
    })

單文件組件+vue-router案例:
2個(gè)組件:first、second代表2個(gè)頁面, 路由文件異步組件方式:

     //傳統(tǒng)寫法:import First from '@/components/First'
    方法一:
            const first = () => import("../components/first.vue")
            const second = () => import("../components/second.vue")
    方法二:
            const first = resolve => require.ensure([], () => resolve( require(../components/first.vue)),  'chunkname1')
            const second = resolve => require.ensure([], () => resolve( require(../components/second.vue)),  'chunkname2')
      //其余配置如以往一樣
      const routes = [
          {
              path: '/',
              component: first
           },
            {
              path: '/',
              component: second
           }
      ]

webpack中利用require.ensure()實(shí)現(xiàn)按需加載

require.ensure()(webpack異步加載|代碼分割)

  • 解釋1:把js模塊獨(dú)立導(dǎo)出一個(gè)個(gè)js文件,然后使用這個(gè)模塊時(shí),webpack會構(gòu)造這個(gè)script dom元素,加入到document.head中,由瀏覽器自動發(fā)起異步請求這個(gè)js文件,再寫個(gè)回調(diào),去定義得到這個(gè)js文件后的業(yè)務(wù)邏輯。
  • 解釋2:webpack 在編譯時(shí),會靜態(tài)地解析代碼中的 require.ensure(),同時(shí)將模塊添加到一個(gè)分開的 chunk 當(dāng)中。這個(gè)新的 chunk 會被 webpack 通過 jsonp 來按需加載。

require.ensure這個(gè)函數(shù)是一個(gè)代碼分離的分割線,表示 回調(diào)里面的require
是我們想要進(jìn)行分割出去的,即require(’./baidumap.js’),把baidumap.js分割出去,形成一個(gè)webpack打包的單獨(dú)js文件。當(dāng)然ensure里面也是可以寫一些同步的require的,如:

    var sync = require('syncdemo.js')   //下面ensure里面也用到
    btn.click(function() {
        require.ensure([], function() {
              var map = require('./map.js') //map.js放在我們當(dāng)前目錄下
              //這個(gè)不會獨(dú)立出去,因?yàn)樗呀?jīng)加載到模塊緩存中了
               var sync = require('syncdemo.js')  
    })
  })

===》ensure會把沒有使用過的require資源進(jìn)行獨(dú)立分成成一個(gè)js文件

ensure語法及參數(shù)解釋

require.ensure(dependencies: string[], callback: function(require),chunkName:string)

  • 第一個(gè)參數(shù):默認(rèn)[],放置當(dāng)前這個(gè)模塊所依賴的其他模塊。比如:假設(shè)A 和 B都是異步的,B中需要A,則B下載之前,先要下載A :require.ensure([‘A.js’], function...),!!!!需要注意:webpack會把參數(shù)里面的依賴異步模塊和當(dāng)前的需要分離出去的異步模塊給一起打包成同一個(gè)js文件,這里可能會出現(xiàn)一個(gè)重復(fù)打包的問題, 假設(shè)A 和 B都是異步的, ensure A 中依賴B,ensure B中 依賴A,那么會生成兩個(gè)文件,都包含A和B模塊。
  • 第二個(gè)參數(shù):當(dāng)所有依賴都加載完成后,webpack會執(zhí)行這個(gè)回調(diào)函數(shù)。require對象的一個(gè)實(shí)現(xiàn)會作為一個(gè)參數(shù)傳遞給這個(gè)回調(diào)函數(shù)。因此,我們可以進(jìn)一步require()依賴和其他模塊提供下一步的執(zhí)行。
  • 第三個(gè)參數(shù),chunkname打包后代碼塊的名字:chunk提供給這個(gè)特定的require.ensure()的chunk的名稱。通過提供 require.ensure() 不同執(zhí)行點(diǎn)相同的名稱,我們可以保證所有的依賴都會一起放進(jìn)相同的 文件束(bundle)。

使用 vue-cli構(gòu)建的項(xiàng)目,在 默認(rèn)情況下 ,執(zhí)行 npm run build 會將所有的js代碼打包為一個(gè)整體。如果想要讓build之后的代碼更便于識別,可配置webpack代碼,單獨(dú)打包自己定義的名字(需要配置chunkFileName和publicPath)

  module.exports = {
        entry:  './src/main.js',
        output: {
              path: path.resolve(__dirname, './dist'),
              publicPath: '/dist/', //是按需加載單獨(dú)打包出來的chunk是以publicPath為基準(zhǔn)來存放的
              filename: 'build.js',
              chunkFilename: 'js/[name]-[chunkhash:8].js' //最終生成的路徑和名字
          }
    }
打包結(jié)果.png
目錄結(jié)果.png

參考地址:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,784評論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,746評論 2 370