webpack源碼分析1

一、打包後文件分析javascript

(function (modules) { // webpackBootstrap
  // The module cache
  //緩存加載的模塊
  var installedModules = {};


  // The require function
  // 下面的這個方法就是 webpack 當中自定義的,它的核心做用就是返回模塊的 exports
  function __webpack_require__(moduleId) {


    // Check if module is in cache
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports;
    }
    // Create a new module (and put it into the cache)
    var module = installedModules[moduleId] = {
      i: moduleId,
      l: false,
      exports: {}
    };


    // Execute the module function,執行的是傳進來的對應鍵值函數,執行以後會把結果掛載到module.export身上
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);


    // Flag the module as loaded
    module.l = true;


    // Return the exports of the module
    return module.exports;
  }


  // expose the modules object (__webpack_modules__)
  __webpack_require__.m = modules;


  // expose the module cache
  __webpack_require__.c = installedModules;


  // define getter function for harmony exports
  __webpack_require__.d = function (exports, name, getter) {
    if (!__webpack_require__.o(exports, name)) {
      Object.defineProperty(exports, name, { enumerable: true, get: getter });
    }
  };


  // define __esModule on exports
  __webpack_require__.r = function (exports) {
    if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
    }
    Object.defineProperty(exports, '__esModule', { value: true });
  };


  // create a fake namespace object
  // mode & 1: value is a module id, require it
  // mode & 2: merge all properties of value into the ns
  // mode & 4: return value when already ns object
  // mode & 8|1: behave like require
  __webpack_require__.t = function (value, mode) {
    if (mode & 1) value = __webpack_require__(value);
    if (mode & 8) return value;
    if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
    var ns = Object.create(null);
    __webpack_require__.r(ns);
    Object.defineProperty(ns, 'default', { enumerable: true, value: value });
    if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key));
    return ns;
  };


  // getDefaultExport function for compatibility with non-harmony modules
  __webpack_require__.n = function (module) {
    var getter = module && module.__esModule ?
      function getDefault() { return module['default']; } :
      function getModuleExports() { return module; };
    __webpack_require__.d(getter, 'a', getter);
    return getter;
  };


  // Object.prototype.hasOwnProperty.call
  __webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); };


  // __webpack_public_path__
  __webpack_require__.p = "";


  // Load entry module and return exports
  return __webpack_require__(__webpack_require__.s = "./src/index.js");
})
  /************************************************************************/
  ({
    "./src/index.js":
      /*! no static exports found */
      (function (module, exports) {
        console.log('index.js內容')
        module.exports = '入口文件導出內容'
      })
  });

/**java

  • 01 打包後的文件就是一個函數自調用,當前函數調用時傳入一個對象
  • 02 這個對象咱們爲了方便將之稱爲是模塊定義,它就是一個鍵值對
  • 03 這個鍵名就是當前被加載模塊的文件名與某個目錄的拼接()
  • 04 這個鍵值就是一個函數,和 node.js 裏的模塊加載有一些相似,會將被加載模塊中的內容包裹於一個函數中
  • 05 這個函數在未來某個時間點上會被調用,同時會接收到必定的參數,利用這些參數就能夠實現模塊的加載操做
    *
  • 06 針對於上述的代碼就至關因而將 {}(模塊定義) 傳遞給了 modules
    */

初始化了一個環境,匿名函數自調用__webpack_require__,模塊ID代表所選模塊,最終返回一個解析了全部依賴關係的模塊node

二、功能函數分析webpack

(function (modules) { // webpackBootstrap
  // The module cache
  // 定義對象用於緩存已加載過的模塊
  var installedModules = {};


  // The require function
  // webpack 自定義的一個加載方法,核心功能就是返回被加載模塊中導出的內容(具體內部是如何實現的,後續再分析)
  function __webpack_require__(moduleId) {


    // Check if module is in cache
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports;
    }
    // Create a new module (and put it into the cache)
    var module = installedModules[moduleId] = {
      i: moduleId,
      l: false,
      exports: {}
    };


    // Execute the module function
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);


    // Flag the module as loaded
    module.l = true;


    // Return the exports of the module
    return module.exports;
  }


  // expose the modules object (__webpack_modules__)
  // 將模塊定義保存一份,經過 m 屬性掛載到自定義的方法身上
  __webpack_require__.m = modules;


  // expose the module cache
  __webpack_require__.c = installedModules;


  // Object.prototype.hasOwnProperty.call
  // 判斷被傳入的對象 obj 身上是否具備指定的屬性 **** ,若是有則返回 true
  __webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); };


  // define getter function for harmony exports
  __webpack_require__.d = function (exports, name, getter) {
    // 若是當前 exports 身上不具有 name 屬性,則條件成立
    if (!__webpack_require__.o(exports, name)) {
      Object.defineProperty(exports, name, { enumerable: true, get: getter });
    }
  };


  // define __esModule on exports
  __webpack_require__.r = function (exports) {
    // 下面的條件若是成立就說明是一個  esModule
    if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
      // Object.prototype.toString.call(exports)
      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
    }
    // 若是條件不成立,咱們也直接在 exports 對象的身上添加一個 __esModule 屬性,它的值就是true
    Object.defineProperty(exports, '__esModule', { value: true });
  };


  // create a fake namespace object
  // mode & 1: value is a module id, require it
  // mode & 2: merge all properties of value into the ns
  // mode & 4: return value when already ns object
  // mode & 8|1: behave like require
  __webpack_require__.t = function (value, mode) {
    // 01 調用 t 方法以後,咱們會拿到被加載模塊中的內容 value
    // 02 對於 value 來講咱們可能會直接返回,也可能會處理以後再返回
    if (mode & 1) value = __webpack_require__(value);
    if (mode & 8) return value;
    if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
    var ns = Object.create(null);
    __webpack_require__.r(ns);
    Object.defineProperty(ns, 'default', { enumerable: true, value: value });
    if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key));
    return ns;
  };


  // getDefaultExport function for compatibility with non-harmony modules
  __webpack_require__.n = function (module) {
    var getter = module && module.__esModule ?
      function getDefault() { return module['default']; } :
      function getModuleExports() { return module; };
    __webpack_require__.d(getter, 'a', getter);
    return getter;
  };


  // __webpack_public_path__
  __webpack_require__.p = "";


  // Load entry module and return exports
  return __webpack_require__(__webpack_require__.s = "./src/index.js");
})
  /************************************************************************/
  ({
    "./src/index.js":
      /*! no static exports found */
      (function (module, exports, __webpack_require__) {
        let name = __webpack_require__(/*! ./login.js */ "./src/login.js")
        console.log('index.js內容執行了')
        console.log(name)
      }),
    "./src/login.js":
      /*! no static exports found */
      (function (module, exports) {
        module.exports = '拉勾教育'
      })
  });

三、CommonJs打包


({
"./src/index.js":
(function (module, exports, __webpack_require__) {

let obj = __webpack_require__(/*! ./login.js */ "./src/login.js")

console.log('index.js內容執行了')
console.log(obj.default, '---->', obj.age)



}),
"./src/login.js":
(function (module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);//給這個模塊加標記
__webpack_require__.d(__webpack_exports__, "age", function () { return age; });//給這個模塊添加age屬性,後面的是getter方法

__webpack_exports__["default"] = ('zcegg');//默認值的添加
const age = 18

})
});

採用esm導出內容引入時採用require方法es6

四、esModule模塊打包web

({
"./src/index.js":
(function (module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
var _login_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./login.js */ "./src/login.js");

console.log('index.js內容加載了')
console.log(_login_js__WEBPACK_IMPORTED_MODULE_0__["default"], '---->', _login_js__WEBPACK_IMPORTED_MODULE_0__["age"])

}),
"./src/login.js":
(function (module, __webpack_exports__, __webpack_require__) {

"use strict";
__webpack_require__.r(__webpack_exports__);
__webpack_require__.d(__webpack_exports__, "age", function () { return age; });

__webpack_exports__["default"] = ('拉勾教育');
const age = 100

})
});

五、功能函數手寫實現json

(function (modules) {
  // 01 定義對象用於未來緩存被加載過的模塊
  let installedModules = {}


  // 02 定義一個 __webpack_require__ 方法來替換 import require 加載操做
  function __webpack_require__(moduleId) {
    // 2-1 判斷當前緩存中是否存在要被加載的模塊內容,若是存在則直接返回
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports
    }


    // 2-2 若是當前緩存中不存在則須要咱們本身定義{} 執行被導入的模塊內容加載
    let module = installedModules[moduleId] = {
      i: moduleId,
      l: false,
      exports: {}
    }


    // 2-3 調用當前 moduleId 對應的函數,而後完成內容的加載
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__)


    // 2-4 當上述的方法調用完成以後,咱們就能夠修改 l 的值用於表示當前模塊內容已經加載完成了
    module.l = true


    // 2-5 加載工做完成以後,要將拿回來的內容返回至調用的位置
    return module.exports
  }


  // 03 定義 m 屬性用於保存 modules
  __webpack_require__.m = modules


  // 04 定義 c 屬性用於保存 cache
  __webpack_require__.c = installedModules


  // 05 定義 o 方法用於判斷對象的身上是否存在指定的屬性
  __webpack_require__.o = function (object, property) {
    return Object.prototype.hasOwnProperty(object, property)
  }


  // 06 定義 d 方法用於在對象的身上添加指定的屬性,同時給該屬性提供一個 getter
  __webpack_require__.d = function (exports, name, getter) {
    if (!__webpack_require__.o(exports, name)) {
      Object.defineProperty(exports, name, { enumerable: true, get: getter })
    }
  }


  // 07 定義 r 方法用於標識當前模塊是 es6 類型
  __webpack_require__.r = function (exports) {
    if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
      Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" })
    }
    Object.defineProperty(exports, '__esModule', { value: true })
  }


  // 08 定義 n 方法,用於設置具體的 getter
  __webpack_require__.n = function (module) {
    let getter = module && module.__esModule ?
      function getDefault() { return module['default'] } :
      function getModuleExports() { return module }


    __webpack_require__.d(getter, 'a', getter)


    return getter
  }


  // 09 定義 P 屬性,用於保存資源訪問路徑
  __webpack_require__.p = ""


  // 10 調用 __webpack_require__ 方法執行模塊導入與加載操做
  return __webpack_require__(__webpack_require__.s = './src/index.js')


})
  ({
    "./src/index.js":
      (function (module, __webpack_exports__, __webpack_require__) {


        "use strict";
        __webpack_require__.r(__webpack_exports__);
        var _login_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./login.js */ "./src/login.js");
        console.log('index.js 執行了')
        console.log(_login_js__WEBPACK_IMPORTED_MODULE_0__["default"], '<------')
        console.log(_login_js__WEBPACK_IMPORTED_MODULE_0__["age"], '<------')
      }),
    "./src/login.js":
      (function (module, __webpack_exports__, __webpack_require__) {
        "use strict";
        __webpack_require__.r(__webpack_exports__);
        __webpack_require__.d(__webpack_exports__, "age", function () { return age; });
        __webpack_exports__["default"] = ('zce是一個帥哥');
        const age = 40
      })


  })

十一、懶加載實現promise

let oBtn = document.getElementById('btn')


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


console.log('index.js執行了')



  ({
    "./src/index.js":
      (function (module, exports, __webpack_require__) {
        let oBtn = document.getElementById('btn')
        oBtn.addEventListener('click', function () {
          __webpack_require__.e(/*! import() | login */ "login").then(__webpack_require__.t.bind(null, /*! ./login.js */ "./src/login.js", 7)).then((login) => {
            console.log(login)
          })
        })
        console.log('index.js執行了')
      })
  });

新的屬性e,t方法緩存

十二、t方法app

__webpack_require__.t = function (value, mode) {
    /**
     * 01 接收二個參數,一個是 value 通常用於表示被加載的模塊id ,第二個值 mode 是一個二進制的數值
     * 02 t 方法內部作的第一件事情就是調用自定義的 require 方法加載value 對應的模塊導出,從新賦值給 value
     * 03 當獲取到了這個 value 值以後餘下的 8 4 ns 2 都是對當前的內容進行加工處理,而後返回使用
     * 04 當mode & 8 成立是直接將 value 返回 ( commonJS )
     * 05 當 mode & 4 成立時直接將 value 返回(esModule)
     * 06 若是上述條件都不成立,仍是要繼續處理 value ,定義一個  ns {}
     *  6-1 若是拿到的 value 是一個能夠直接使用的內容,例如是一個字符串,將它掛載到 ns 的 default 屬性上
     *  6-2 若是不是,就把這個對象的鍵值對一個一個賦值到ns上
     */
    if (mode & 1) value = __webpack_require__(value);
    if (mode & 8) return value;
    if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
    var ns = Object.create(null);
    __webpack_require__.r(ns);
    Object.defineProperty(ns, 'default', { enumerable: true, value: value });
    if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key));
    return ns;
  };

// 11 定義 t 方法,用於加載指定 value 的模塊內容,以後對內容進行處理再返回

__webpack_require__.t = function (value, mode) {
    // 01 加載 value 對應的模塊內容( value 通常就是模塊 id )
    // 加載以後的內容又從新賦值給 value 變量
    if (mode & 1) {
      value = __webpack_require__(value)
    }


    if (mode & 8) {  // 加載了能夠直接返回使用的內容
      return value
    }


    if ((mode & 4) && typeof value === 'object' && value && value.__esModule) {
      return value
    }


    // 若是 8 和 4 都沒有成立則須要自定義 ns 來經過 default 屬性返回內容
    let ns = Object.create(null)


    __webpack_require__.r(ns)


    Object.defineProperty(ns, 'default', { enumerable: true, value: value })


    if (mode & 2 && typeof value !== 'string') {
      for (var key in value) {
        __webpack_require__.d(ns, key, function (key) {
          return value[key]
        }.bind(null, key))
      }
    }


    return ns
  }

1三、懶加載

(function (modules) { // webpackBootstrap
  // install a JSONP callback for chunk loading
  function webpackJsonpCallback(data) {
    var chunkIds = data[0];
    var moreModules = data[1];
    // add "moreModules" to the modules object,
    // then flag all "chunkIds" as loaded and fire callback
    var moduleId, chunkId, i = 0, resolves = [];
    for (; i < chunkIds.length; i++) {
      chunkId = chunkIds[i];
      if (Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
        resolves.push(installedChunks[chunkId][0]);
      }
      installedChunks[chunkId] = 0;
    }
    for (moduleId in moreModules) {
      if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
        modules[moduleId] = moreModules[moduleId];
      }
    }
    if (parentJsonpFunction) parentJsonpFunction(data);


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


  };


  // The module cache
  var installedModules = {};


  // object to store loaded and loading chunks
  // undefined = chunk not loaded, null = chunk preloaded/prefetched
  // Promise = chunk loading, 0 = chunk loaded
  var installedChunks = {
    "main": 0
  };


  // script path function
  function jsonpScriptSrc(chunkId) {
    return __webpack_require__.p + "" + chunkId + ".built.js"
  }


  // The require function
  function __webpack_require__(moduleId) {


    // Check if module is in cache
    if (installedModules[moduleId]) {
      return installedModules[moduleId].exports;
    }
    // Create a new module (and put it into the cache)
    var module = installedModules[moduleId] = {
      i: moduleId,
      l: false,
      exports: {}
    };


    // Execute the module function
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);


    // Flag the module as loaded
    module.l = true;


    // Return the exports of the module
    return module.exports;
  }


  // This file contains only the entry chunk.
  // The chunk loading function for additional chunks
  __webpack_require__.e = function requireEnsure(chunkId) {
    var promises = [];




    // JSONP chunk loading for javascript


    var installedChunkData = installedChunks[chunkId];
    if (installedChunkData !== 0) { // 0 means "already installed".


      // a Promise means "currently loading".
      if (installedChunkData) {
        promises.push(installedChunkData[2]);
      } else {
        // setup Promise in chunk cache
        var promise = new Promise(function (resolve, reject) {
          installedChunkData = installedChunks[chunkId] = [resolve, reject];
        });
        promises.push(installedChunkData[2] = promise);


        // start chunk loading
        var script = document.createElement('script');
        var onScriptComplete;


        script.charset = 'utf-8';
        script.timeout = 120;
        if (__webpack_require__.nc) {
          script.setAttribute("nonce", __webpack_require__.nc);
        }
        script.src = jsonpScriptSrc(chunkId);


        // create error before stack unwound to get useful stacktrace later
        var error = new Error();
        onScriptComplete = function (event) {
          // avoid mem leaks in IE.
          script.onerror = script.onload = null;
          clearTimeout(timeout);
          var chunk = installedChunks[chunkId];
          if (chunk !== 0) {
            if (chunk) {
              var errorType = event && (event.type === 'load' ? 'missing' : event.type);
              var realSrc = event && event.target && event.target.src;
              error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
              error.name = 'ChunkLoadError';
              error.type = errorType;
              error.request = realSrc;
              chunk[1](error);
            }
            installedChunks[chunkId] = undefined;
          }
        };
        var timeout = setTimeout(function () {
          onScriptComplete({ type: 'timeout', target: script });
        }, 120000);
        script.onerror = script.onload = onScriptComplete;
        document.head.appendChild(script);
      }
    }
    return Promise.all(promises);
  };


  // expose the modules object (__webpack_modules__)
  __webpack_require__.m = modules;


  // expose the module cache
  __webpack_require__.c = installedModules;


  // define getter function for harmony exports
  __webpack_require__.d = function (exports, name, getter) {
    if (!__webpack_require__.o(exports, name)) {
      Object.defineProperty(exports, name, { enumerable: true, get: getter });
    }
  };


  // define __esModule on exports
  __webpack_require__.r = function (exports) {
    if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
      Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
    }
    Object.defineProperty(exports, '__esModule', { value: true });
  };


  // create a fake namespace object
  // mode & 1: value is a module id, require it
  // mode & 2: merge all properties of value into the ns
  // mode & 4: return value when already ns object
  // mode & 8|1: behave like require
  __webpack_require__.t = function (value, mode) {
    if (mode & 1) value = __webpack_require__(value);
    if (mode & 8) return value;
    if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
    var ns = Object.create(null);
    __webpack_require__.r(ns);
    Object.defineProperty(ns, 'default', { enumerable: true, value: value });
    if (mode & 2 && typeof value != 'string') for (var key in value) __webpack_require__.d(ns, key, function (key) { return value[key]; }.bind(null, key));
    return ns;
  };


  // getDefaultExport function for compatibility with non-harmony modules
  __webpack_require__.n = function (module) {
    var getter = module && module.__esModule ?
      function getDefault() { return module['default']; } :
      function getModuleExports() { return module; };
    __webpack_require__.d(getter, 'a', getter);
    return getter;
  };


  // Object.prototype.hasOwnProperty.call
  __webpack_require__.o = function (object, property) { return Object.prototype.hasOwnProperty.call(object, property); };


  // __webpack_public_path__
  __webpack_require__.p = "";


  // on error function for async loading
  __webpack_require__.oe = function (err) { console.error(err); throw err; };


  var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || [];
  var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);//重寫push方法
  jsonpArray.push = webpackJsonpCallback;
  jsonpArray = jsonpArray.slice();
  for (var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
  var parentJsonpFunction = oldJsonpFunction;




  // Load entry module and return exports
  return __webpack_require__(__webpack_require__.s = "./src/index.js");
})
  /************************************************************************/
  ({
    "./src/index.js":
      (function (module, exports, __webpack_require__) {
        let oBtn = document.getElementById('btn')
        oBtn.addEventListener('click', function () {
          __webpack_require__.e(/*! import() | login */ "login").then(__webpack_require__.t.bind(null, /*! ./login.js */ "./src/login.js", 7)).then((login) => {
            console.log(login)
          })
        })
        console.log('index.js執行了')
      })
  });

1四、懶加載手寫實現

function webpackJsonpCallback(data) {//合併模塊定義,改變promise狀態執行後續行爲

//獲取須要動態加載的模塊id
var chunkIds = data[0];

//獲取須要被動態加載的模塊依賴關係
var moreModules = data[1];

// add "moreModules" to the modules object,
// then flag all "chunkIds" as loaded and fire callback
var moduleId, chunkId, i = 0, resolves = [];

for (; i < chunkIds.length; i++) {

chunkId = chunkIds[i];

if (Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {

resolves.push(installedChunks[chunkId][0]);
}
installedChunks[chunkId] = 0;

}
for (moduleId in moreModules) {

if (Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {

modules[moduleId] = moreModules[moduleId];

}
}
if (parentJsonpFunction) parentJsonpFunction(data);



while (resolves.length) {

resolves.shift()();
}


};


//實現json加載內容,利用promise來實現異步加載操做
__webpack_require__.e = function requireEnsure(chunkId) {

var promises = [];



// JSONP chunk loading for javascript
// 獲取chunkid對應的chunk,是否已經完成加載
var installedChunkData = installedChunks[chunkId];

if (installedChunkData !== 0) { // 0 means "already installed".



// a Promise means "currently loading".
if (installedChunkData) {

promises.push(installedChunkData[2]);
} else {

// setup Promise in chunk cache
var promise = new Promise(function (resolve, reject) {

installedChunkData = installedChunks[chunkId] = [resolve, reject];

});
promises.push(installedChunkData[2] = promise);//下標爲2是參考的源碼



// start chunk loading
var script = document.createElement('script');

var onScriptComplete;



script.charset = 'utf-8';

script.timeout = 120;

if (__webpack_require__.nc) {

script.setAttribute("nonce", __webpack_require__.nc);

}
script.src = jsonpScriptSrc(chunkId);



// create error before stack unwound to get useful stacktrace later
var error = new Error();

onScriptComplete = function (event) {

// avoid mem leaks in IE.
script.onerror = script.onload = null;

clearTimeout(timeout);
var chunk = installedChunks[chunkId];

if (chunk !== 0) {

if (chunk) {

var errorType = event && (event.type === 'load' ? 'missing' : event.type);

var realSrc = event && event.target && event.target.src;

error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';

error.name = 'ChunkLoadError';

error.type = errorType;

error.request = realSrc;

chunk[1](error);
}
installedChunks[chunkId] = undefined;

}
};
var timeout = setTimeout(function () {

onScriptComplete({ type: 'timeout', target: script });

}, 120000);

script.onerror = script.onload = onScriptComplete;

document.head.appendChild(script);
}
}
return Promise.all(promises);

};
相關文章
相關標籤/搜索