webpack 異步組件的缺陷

webpack自己自帶切割代碼(code splitting)的功能,腳本按需加載,簡單好用html

用法以下:vue

require.ensure(["module-a", "module-b"], function(require) {
    var a = require("module-a")
    // ...
})

//或

require(['./my-async-component'], resolve, reject) //vue組件自帶錯誤回掉方法

可是,該功能也不是完美的,在3g、4g網絡下出現了沒法加載異步組件的問題!!!坑爹呀!!!webpack

通過分析,得出下面的結論:git

一、運營商3g、4g網絡 階段性斷網 ,尤爲 聯通 最嚴重
二、webpack自己 沒法捕獲異步組件加載失敗 的狀況 (webpack2支持捕獲組件狀態github

既然第一個問題沒法解決,那咱們就解決第二個問題。web


方法一(不可分離公共代碼):npm

一、 安裝 require-error-handler-webpack-plugin 插件,用它捕獲異步組件的加載失敗的狀態網絡

// webpack.config.js

var  requireErrorHandlerPlugin = require('require-error-handler-webpack-plugin'),
    JsonpMainTemplatePlugin = require('webpack/lib/JsonpMainTemplatePlugin')

二、 使用這個插件app

// webpack.config.js

plugins: [
    new requireErrorHandlerPlugin.JsonpErrorHandlerPlugin(JsonpMainTemplatePlugin),
    new requireErrorHandlerPlugin.RequireEnsureErrorHandlerPlugin(),
    new requireErrorHandlerPlugin.AMDRequireErrorHandlerPlugin()
]

三、項目中使用方法(這個方法不能徹底遏制,可是能夠減小加載失敗的機率)異步

// app.vue

export default {
    components:{
        a: (resolve, reject) => {
            const tryMax = 15
            let tryCount = 0,
                _time = null //隔1.5秒執行一次

            getComponents()
            
            //遞歸調用組件
            //由於運營商網絡會出現短暫的斷網現象,因此每隔1500ms就喚醒一次,對多喚醒11次
            function getComponents() {
                require(['../view/a'], (response) => {
                    //成功後執行
                    resolve(response)
                }, () => {
                    //異步組件加載失敗後調用
                    
                    tryCount += 1

                    if (tryCount > tryMax) { // 若超出最大嘗試次數則 reject
                        reject()
                    } else {
                        _time = setInterval(() => {
                            clearInterval(_time)
                            getComponents()
                        }, 1500)
                    }
                })
            }
        }
    }
}

方法二(推薦,可分離公共代碼):

一、 安裝 async-module-loader 插件,用它捕獲異步組件的加載失敗的狀態

// webpack.config.js

var  AsyncModulePlugin = require('async-module-loader/plugin')

二、 使用這個插件

// webpack.config.js

plugins: [
    new AsyncModulePlugin()
]

三、項目中使用方法

// common.js

//按需加載組件的公共方法,由於運營商網絡會出現短暫的斷網現象,因此每隔1500ms就喚醒一次,對多喚醒11次
function getComponents(requireModel, tryMax, tryCount, resolve, reject) {
    let _time = null

    requireModel(function onLoad(response) {
        resolve(response)
    }, function onError() {
        tryCount += 1

        if (tryCount > tryMax) { // 若超出最大嘗試次數則 reject
            reject()
        } else {
            _time = setInterval(() => {
                clearInterval(_time)
                getComponents(requireModel, tryMax, tryCount, resolve, reject)
            }, 1500)
        }
    })
}

// app.vue

export default {
    components:{
        a: (resolve, reject) => {
            //調用方式
           getComponents(require('async-module!./view/Login'), 10, 0, resolve, reject)
        },
        b: (resolve, reject) => {
            //調用方式
           getComponents(require('async-module!./view/help'), 10, 0, resolve, reject)
        }
    }
}

當項目訪問量很大,甚至超過 1000萬 pv/天的訪問量,就會發現一些噁心的問題,而這些問題的暴露都要感謝咱們的用戶,由於他們,咱們纔會知道運營商網絡的不穩定性,知道了咱們代碼中的缺陷

相關文章
相關標籤/搜索