What will require. Ensure be packaged into?

First, let’s take a look at what webpack looks like when you use Require. ensure in your code

require.ensure([], function () {
    let module2 = require("./module2")
    console.log(module2)
});
Copy the code

Will be compiled by Webpack like this

// The argument 0 is the id of the code block generated for module2
__webpack_require__.e( / *! require.ensure */ 0) 
    .then((function () {
        let module2 = __webpack_require__( / *! ./module2 */ "./module2.js")
        console.log(module2)
    })
    ...// The following code is omitted, mainly doing exception handling
Copy the code

The __webpack_require__. E returns a promise, and the second argument you pass to require.ensure is a promise callback that holds the asynchronously loaded module2

__webpack_require__ is the equivalent of the require method, which takes asynchronously loaded modules, in this case module2

How does require. Ensure implement asynchronous loading? Got the promise?

To put it simply:

// Define a global array object
widow.webpackJsonp = []
// Override the push method of this
webpackJsonp.push = webpackJsonpCallback;

function webpackJsonpCallback(data) {
    var chunkIds = data[0];
    var moreModules = data[1];
    var executeModules = data[2];
    var moduleId, chunkId, i = 0,
        resolves = [];
    for (; i < chunkIds.length; i++) {
        chunkId = chunkIds[i];
        if (Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
            // When a promise is created in __webpack_require__.e,
            InstalledChunks [chunkId] = [resolve, reject];
            // installedChunks[chunkId][0] is the promise. Resolve method
            resolves.push(installedChunks[chunkId][0]);
        }
        // installedChunks[chunkId] is set to 0 to determine whether the module is successfully loaded.
        // script.onload will also be used to determine whether the load failed, and display a message
        installedChunks[chunkId] = 0;
    }
    while(resolves.length) { resolves.shift()(); }... }; __webpack_require__.e =function (chunkId) {
    var promises = [];
    // Get the current module to be loaded from installedChunks
    var installedChunkData = installedChunks[chunkId];
    if(installedChunkData ! = =0) { // 0 indicates that the loading is successful
        // Create a promise and store resolve and reject in the array
        var promise = new Promise(function (resolve, reject) {
            installedChunkData = installedChunks[chunkId] = [resolve, reject];
        });
        promises.push(promise);
        // Create a script tag
        var script = document.createElement('script');
        // Set the request address
        script.src = chunkId + ".bundle.js";
        // Listen for successful and failed script loading events
        script.onerror = script.onload = function (event) {
            // Remove the module after loading
            var chunk = installedChunks[chunkId];
            // If the load succeeds, chunk will be 0
            // If the load fails, the user fails to load
            if(chunk ! = =0) {
                Chunk [1] is actually the reject function of promise
                var error = {
                    message: 'Loading chunk ' + chunkId + ' failed.';
                }
                chunk[1](error); }};// Tags are inserted into the DOM
        document.head.appendChild(script);
    }
    return Promise.all(promises);
}
Copy the code

Module2. Js after packaging

(window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0] and {/ * * * / "./module2.js":
/ *! * * * * * * * * * * * * * * * * * * * *! * \! *** ./module2.js ***! \ * * * * * * * * * * * * * * * * * * * * /
/ *! no static exports found */
/ * * * / (function(module.exports) {

eval(Module.exports = function () {\n console.log(' ha ha ha ha ')\n}\n\n//# sourceURL=webpack:///./module2.js?");

/ * * * /}}));Copy the code

Implementation step resolution

  • 1 Create apromise[resolve, reject]depositinstalledChunks[chunkId]
var promise = new Promise(function (resolve, reject) {
    installedChunkData = installedChunks[chunkId] = [resolve, reject];
});
Copy the code
  • 2 Create ascriptTag, set itsrcTo load this module for the actual requested address, givescriptLabel the bindingonloadEvent handler to handle load failures
  • 3 module2.jsWhen loaded, it’s actually a callwebpackJsonpthepushMethod, becausepushThe method is rewritten as webpackJsonpCallback; Therefore,pushCalled when the method is called webpackJsonpCallback
  • 4 webpackJsonpCallbackWhen executed, get the callpushMethodchunkIdSet the module’s load success status to 0
installedChunks[chunkId] = 0;
Copy the code
  • 5 frominstalledChunksRemove thechunkIdCorresponding moduleresolveMethod to retrieve the component after execution

Ensure is used in Vue

const home = r => require.ensure([], () => r(require('.. /page/home/home')), 'home')

Ensure ([], () => resolve(require(‘.. /page/home/home’)), ‘home’)

Why do you write that? Since this is the syntax of vUE asynchronous components, you can see the vUE official website for asynchronous components, as shown below

Vue.component('async-example'.function (resolve, reject) { 
    setTimeout(function () { 
        // Pass the component definition to the 'resolve' callback
        resolve({ 
           template: '
      
I am async!
'
})},1000)})Copy the code

The then method of the promise returned by require. Ensure calls require(‘.. /page/home/home’) takes the compile result of the home component (the component’s object) and passes the component object as a parameter to the resolve method provided by VUE. Vue takes the definition of the component and can proceed with its component rendering logic