Continue above, first look at the last time did not understand the two points, and then read the source code to write a simple version of asynchronous loading;

The last code had two places in webpackJsonpCallck as follows

webpackJsonCallback = (parentChunkLoadingFunction, data) {
    var [modules, moreModules, runtime] = data;
    / /... The module installation is omitted
    if (runtime) runtime(__webpack_require__);
    if (parentChunkLoadingFunction) parentChunkLoadingFunction(data) 
    / /... Script loading resolve is omitted
}
Copy the code

The call to this function is currified, filling parameters in two steps;

  • Case 1: Runtime loads first

step1:

chunkLoadingGloabl.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
Copy the code

step2(async module invoke):

// When the module is packaged as an entry, it is passed to runtime to start execution
(chunkLoadingGlobal.push([[chunkId], [modules], ?runtime]))();
Copy the code
  • Case 2: Modules are loaded first

Modules can be loaded after other modules when running from Webpack4. For details, click the link.

chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null.0));
Copy the code

[chunkLoadingGloabl, moreModules,? Runtime];

  • ChunkIds (loaded chunkId) is used for resolve corresponding to the chunk Load Promise;
  • MoreModules stores the actual module content for installation;
  • Runtime is used to execute the entry module;

For WebPack4, you can print webpackJsonp on the console. For WebPack5, you can print webpackChunkwebpack_build.

Then we will implement a low version of the module load, webpack this code should be generated after parsing, parsing process has not yet in-depth understanding, we can refer to this old man wrote Babel import syntax js_ in-depth principle: Babel principle and Babel plug-in practice; So first implement the main module loading, similar to AMD loading:

Here is a crude version of the implementation:

(function (global) {
    let modules = {};
    let pathMap = {};
    function define (deps, fn) {
        if (typeof deps === 'function') { modules = {... modules, ... deps()};return
        }
        for (let [index, item] of deps.entries()) {
            if (modules[item]) {
                deps[index] = Promise.resolve(modules[item])
            } else {
                let structrue = [];
                deps[index] = new Promise((resolve, reject) = > {
                    structrue = [() = >resolve(modules[item]), reject] }); loadScript(item, structrue); }}Promise.all(deps).then(res= > {
            let result = fn.apply(null, res);
            if(result) { modules = {... modules, ... result} } }) }// Used to configure the module loading path
    define.config = function (config) {
        pathMap = config.paths
    }

    let inProgress = {};
    function loadScript (id, structure) {
        const url = pathMap[id];
        if (inProgress[url]) {
            // The module is already requested;
            inProgress[url].push(structure);
            return;
        }
        const script = document.createElement('script');
        document.body.append(script);
        script.src = url;
        inProgress[url] = [structure];
        script.onload = function () {
            let callbacks = inProgress[url];
            delete inProgress[url];
            callbacks.forEach(([resolve, reject]) = > {
                resolve();
            });
            document.body.removeChild(script);
        }
        script.onerror = function (err) {
            let callbacks = inProgress[url];
            delete inProgress[url];
            callbacks.forEach(([resolve, reject]) = > {
                reject(err);
            });
            document.body.removeChild(script); }}global.define = define; }) (window);
Copy the code

The usage is as follows:

<script src="./module.js"></script>
<script>
define.config({
    paths: {mutilple: './multiple.js'}}); define(['mutilple'].function (mutilple) {
    console.log(mutilple);
    console.log(mutilple(2.3));
})
</script>
Copy the code

It’s fun to look at the compiled code and just feel that the resolve and reject promise can be passed somewhere else.

Well, this is the end of the overall analysis, in fact, look at the compiled code and source code, guess the true intention of the author is not very easy; If you have any questions or mistakes, you can leave comments and discuss them.