zoukankan      html  css  js  c++  java
  • webpack模块化原理

    https://segmentfault.com/a/1190000010349749

    commonJS

    案例:

    //index.js
    'use strict';
    var bar = require('./bar');
    function foo() {
        return bar();
    }
    
    //bar.js
    'use strict';
    exports.bar = function () {
        return 1;
    }
    
    //配置
    var path = require("path");
    module.exports = {
        entry: path.join(__dirname, 'index.js'),
        output: {
            path: path.join(__dirname, 'outs'),
            filename: 'index.js'
        },
    };

    打包后生成代码如下:

    (function(modules) { // webpackBootstrap
        // The module cache
        var installedModules = {};
        // 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;
        }
        // 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, {
                    configurable: false,
                    enumerable: true,
                    get: getter
                });
            }
        };
        // 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 = 0);
    })
    /************************************************************************/
    ([
    /* 0 */
    (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    var bar = __webpack_require__(1);
    bar();
    
    }),
    /* 1 */
    (function(module, exports, __webpack_require__) {
    
    "use strict";
    
    exports.bar = function () {
        return 1;
    }
    
    })
    ]);

      对以上代码进行简化:

    (function (modules) {/* 省略函数内容 */})
    ([
    function (module, exports, __webpack_require__) {
        /* 模块index.js的代码 */
    },
    function (module, exports, __webpack_require__) {
        /* 模块bar.js的代码 */
    }
    ]);

      可以发现,以上就是一个IIFE,两个模块分别以函数的形式,存放到一个modules数组中,然后传递给匿名函数,执行。将这个匿名函数的代码抽取出来:

    // 1、模块缓存对象
    var installedModules = {};
    // 2、webpack实现的require
    function __webpack_require__(moduleId) {
        // 3、判断是否已缓存模块
        if(installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        // 4、缓存模块
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: false,
            exports: {}
        };
        // 5、调用模块函数
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // 6、标记模块为已加载
        module.l = true;
        // 7、返回module.exports
        return module.exports;
    }
    // 8、require第一个模块
    return __webpack_require__(__webpack_require__.s = 0);

    installedModules对象存放了对应模块的信息,如模块id,导出的值和是否已经执行过

    webpack_require用于根据id加载一个模块,如果这个模块已经执行过,则直接返回导出的值,否则执行这个模块,然后标记这个模块已经执行,最后导出值

    Code Spliting

    https://segmentfault.com/a/1190000011435407

    使用方式如下:

    // index.js
    'use strict';
    import(/* webpackChunkName: "foo" */ './foo').then(foo => {
        console.log(foo());
    })
    import(/* webpackChunkName: "bar" */ './bar').then(bar => {
        console.log(bar());
    })
    
    // foo.js
    'use strict';
    exports.foo = function () {
        return 2;
    }
    
    // bar.js
    'use strict';
    exports.bar = function () {
        return 1;
    }
    
    // 配置文件
    var path = require("path");
    module.exports = {
        entry: path.join(__dirname, 'index.js'),
        output: {
            path: path.join(__dirname, 'outs'),
            filename: 'index.js',
            chunkFilename: '[name].bundle.js'
        },
    };

      以上打包出来,模块会在独立的文件中,这些独立出来的模块文件内容大致如下:

    webpackJsonp([0],[
    /* 0 */,
    /* 1 */
    /***/ (function(module, exports, __webpack_require__) {
    "use strict";
    exports.foo = function () {
        return 2;
    }
    /***/ })
    ]);

      当需要获取这些模块文件时,通过 webpack_require.e 动态插入一个script标签来加载以上文件,然后返回一个promise来通知外界这个模块的加载情况,用于执行回调方法。这个promise有可能已经处于resolve状态,也可能处理等待状态。

      以上script内容下载完成后,webpackJsonp就会执行,参数就是模块的代码(这种获取模块的方式类似于Jsonp),webpackJsonp就会获取对应模块的Promise,然后改变promise的状态。这样一来其他地方从webpack_require.e获取到的promise,对应的回调方法就会执行,代表模块加载完成。

  • 相关阅读:
    应对https协议的下载方式
    订单峰值激增 230%,Serverless 如何为世纪联华降本超 40%?|双11 云原生实践
    阿里云函数计算发布新功能,支持容器镜像,加速应用 Serverless 进程
    专访阿里云 Serverless 负责人:无服务器不会让后端失业
    从零入门 Serverless | SAE 的远程调试和云端联调
    我在阿里巴巴做 Serverless 云开发平台
    高德最佳实践:Serverless 规模化落地有哪些价值?
    [图论总结1]最大独立集(例题:Code Names)
    Excel导入SQL工具【3.02】
    学习笔记助手【2.01】base1 更新
  • 原文地址:https://www.cnblogs.com/hellohello/p/9044824.html
Copyright © 2011-2022 走看看