动态

详情 返回 返回

webpack,單文件懶加載分析實現 - 动态 详情

log.js文件

module.exports ="lazy load logger"

index.js文件

let oBtn = document.getElementById('btn')

oBtn.addEventListener('click', function () {
    import( /*webpackChunkName: "log"*/ './log.js').then((log) => {
        console.log(log)
    })
})
console.log('index.js內容')

點擊按鈕時,控制枱顯示lazy load logger
webpack在打包後,比之前的單文件加載多出了幾件事情。懶加載的實現主要通過Promise來實現。
實現懶加載,要調用__webpack_require__.e方法,e方法是一個promise狀態保存。e方法中,jsonP創建srcipt標籤,指定src,通過Promise.all把狀態往後傳,在過程中,動態加載要被導入的內容,這裏會通過window['webpackJsonP]調用push方法.調用webpackJsonpCallback方法,執行成功的resolve方法,__webpack_require__.e後的then方法通過__webpack_require__.t方法加載log中的內容放在value中保存.這裏多出的兩個操作一個是jsonP,一個是__webpack_require__.e

// 定義webpackJsonpCallback,合併模塊定義,改變promise狀態,還有之後的then操作
    function webpackJsonpCallback(data) {
        // 獲取要被動態加載的模塊id
        let chunkIds = data[0];
        //  獲取需要被動態加載模塊的依賴關係對象
        let moreModules = data[1]
        let chunkId
        let resolves = []
        // 循環判斷chunkIds裏對應的模塊內容是否已經完成加載
        for (let i = 0; i < chunkIds.length; i++) {
            chunkId = chunkIds[i]
            if (Object.prototype.hasOwnProperty.call(inStalledChunks, chunkId) && inStalledChunks[chunkId]) {
                //數組順序,resolve,reject,promise,這裏是已經加載,所以是0
                resolves.push(inStalledChunks[chunkId][0])
            }
            // 更新chunk狀態
            inStalledChunks[chunkId] = 0;
        }

        for (let moduleId in moreModules) {
            if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
                modules[moduleId] = moreModules[moduleId]
            }
        }

        while (resolves.length) {
            resolves.shift()()
        }
    }

    // 定義inStalledChunks 用於標識某個chunkId對應的chunk是否完成加載
    let inStalledChunks = {
        main: 0
    }

    // 定義jsonpScriptSrc實現src的處理
    function jsonpScriptSrc(chunkId) {
        return __webpack_require__.p + "" + chunkId + '.built.js'
    }

    // 定義e方法,用於實現 :實現jsonP異步加載,利用promise來實現異步加載操作
    __webpack_require__.e = function (chunkId) {
        // 定義一個數組用於存放promise
        let promises = [];
        // 獲取chunkId對應的chunk是否已經完成了加載
        let installedChunkData = inStalledChunks[chunkId]
        // 依據當前是否已完成加載的狀態來執行後續的邏輯
        if (installedChunkData !== 0) {
            if (installedChunkData) {
                // push一個完整的promise
                promises.push(installedChunkData[2])
            } else {
                // 執行加載操作
                let promise = new Promise((resolve, reject) => {
                    installedChunkData = inStalledChunks[chunkId] = [resolve, reject]
                })
                promises.push(installedChunkData[2] = promise)
                // 創建標籤
                let script = document.createElement('script')
                // 設置src
                script.src = jsonpScriptSrc(chunkId)
                // 寫入script標籤
                document.head.appendChild(script)
            }
        }

        // 執行promise
        return Promise.all(promises)
    }
user avatar icecreamlj 头像 inslog 头像 imba97 头像 shuyuanutil 头像 johanazhu 头像 snowwolfarden 头像 changlina 头像 reddish 头像 mincloud 头像 danjuanfe 头像 sparkler 头像 maomaoxiaobo 头像
点赞 29 用户, 点赞了这篇动态!
点赞

Add a new 评论

Some HTML is okay.