精华内容
下载资源
问答
  • webpack打包原理

    2020-03-20 10:08:27
    webpack打包原理 作者:Dinosaur 标签:webpack 发布于:2020/3/19 下午5:40 浏览:(9) webpack打包原理 2020年3月19日 17:19 上节《浅谈webpack》中,笔者简单介绍了一下webapck的工作原理,这节我们从源码的角度上,...

    webpack打包原理
    作者:Dinosaur 标签:webpack 发布于:2020/3/19 下午5:40 浏览:(9)
    webpack打包原理

    2020年3月19日

    17:19

      上节《浅谈webpack》中,笔者简单介绍了一下webapck的工作原理,这节我们从源码的角度上,较为深刻的探究一下(就是不是特别深刻的意思):
    
      上节我们已经知道了,webpack因为要兼顾commonjs和es6的引入导出方式,而选择用函数调用的方式打包代码,那么我们今天看一下,打包后的dist目录下的main文件,到底是怎么运作的。
    
      首先,我们在src目录下,写入两个文件,一个是a.js,一个是index.js,大家都知道webpack打包时是从src目录下的index.js来分析依赖关系的,这里直接贴上两个文件的代码:
    

    a.js:

    console.log(“module a”);

    var a = “hello my name is little a”

    module.exports = a;

    Index.js:

    console.log(“module index”);

    require("./a.js");

    console.log(“调用完成”);

    webpack的打包结果输出顺序为:module index , module a hello xxxx,调用完成。

    下面来一步一步写一下webpack的main源码,首先大家要知道,webpack会将src中的文件变成一个对象,对象中的键是文件目录,值为一个函数,函数体是相应文件内容,代码如下:

    var modules = {

        "../src/index.js": function (module, exports,require) {
    
            console.log("module index");
    
    
    
            require("../src/a.js");
    
    
    
            console.log("调用完成");//index文件的代码
    
        },
    
        "../src/a.js": function (module, exports) {
    
            console.log("module a");
    
            const a = "hello my name is little a"
    
            module.exports = a;//a文件的代码
    
        }
    

    }

      从文件中可以看出,webpack中不能出现传统的引入文件或者抛出的写法,这里用参数将其传递进去。
    
    
    
      为了不产生命名冲突,我们将其写入立即执行函数,直接将modules作为其参数传入
    

    (function(modules){

    })({

    "../src/index.js": function (module, exports,require) {
    
        console.log("module index");
    
        const result = require("../src/a.js");
    
        console.log("调用完成");
    
    },
    
    "../src/a.js": function (module, exports) {
    
        console.log("module a");
    
        const a = "hello my name is little a"
    
        module.exports = a;
    
    }
    

    })

      首先肯定要require(’../src.index.js‘),来分析依赖关系,但是没有require,只能自己写
    

    (function(modules){

    function require(src) {
    
        const func = modules[src];//根据传入的src,调用不同的函数。
    
        func(module,module.exports,require)
    
    }
    
    require("../src/index.js");
    

    })({

    "../src/index.js": function (module, exports,require) {
    
        console.log("module index");
    
        const result = require("../src/a.js");
    
        console.log("调用完成");
    
    },
    
    "../src/a.js": function (module, exports) {
    
        console.log("module a");
    
        const a = "hello my name is little a"
    
        module.exports = a;
    
    }
    

    })

    require函数中再来调用modules(被传入的对象,)中的函数,这个函数需要将module,module.exports和require传入。但是没有前两个怎么办呢?自己写:

    //防止命名冲突,使用立即执行函数。

    (function (modules) {

    function require(src) {
    
        const func = modules[src];//根据传入的src,调用不同的函数。
    
        const module = {
    
            exports: {}
    
        }//自己写的module
    
        func(module,module.exports,require)
    
        const result = module.exports;//拿到结果
    
        return result;
    
    }
    
    require("../src/index.js");
    

    })({

    "../src/index.js": function (module, exports,require) {
    
        console.log("module index");
    
        const result = require("../src/a.js");
    
        console.log("调用完成");
    
    },
    
    "../src/a.js": function (module, exports) {
    
        console.log("module a");
    
        const a = "hello my name is little a"
    
        module.exports = a;
    
    }
    

    });

    读者可以自行分析一下上述代码运作过程,其实就是webpack打包原理的简化版。

    结束语:

    前端技术博大精深,笔者才学疏浅,上述所述均为自身观点,而非标准答案,若有疑惑、指正,欢迎在

    www.dinosaurcoder.com 留言!

    展开全文
  • Webpack打包原理

    万次阅读 2019-04-01 20:10:25
    webpack只是一个打包模块的机制,只是把依赖的模块转化成可以代表这些包的静态文件。 webpack就是识别你的 入口文件。识别你的模块依赖,来打包你的代码。至于你的代码使用的是commonjs还是amd或者es6的import。...

    webpack只是一个打包模块的机制,只是把依赖的模块转化成可以代表这些包的静态文件。

    webpack就是识别你的 入口文件。识别你的模块依赖,来打包你的代码。至于你的代码使用的是commonjs还是amd或者es6的import。webpack都会对其进行分析。来获取代码的依赖。

    webpack做的就是分析代码,转换代码,编译代码,输出代码。webpack本身是一个node的模块,所以webpack.config.js是以commonjs形式书写的(node中的模块化是commonjs规范的)

    webpack中每个模块有一个唯一的id,是从0开始递增的。整个打包后的bundle.js是一个匿名函数自执行。参数则为一个数组。数组的每一项都为个function。function的内容则为每个模块的内容,并按照require的顺序排列。

    // webpack.config.js
    module.exports = {
      entry:'./a.js',
      output:{
        filename:'bundle.js'
      }
    };
    
    // a.js
    var b = require('./b.js');
    
    console.log('a');
    
    b.b1();
    
    // b.js
    exports.b1 = function () {
      console.log('b1')
    };
    
    exports.b2 = function () {
      console.log('b2')
    };
    

    以上代码我们打包处理的js为

    // bundle.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] = {
    /******/            exports: {},
    /******/            id: moduleId,
    /******/            loaded: false
    /******/        };
    
    /******/        // Execute the module function
    /******/        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
    
    /******/        // Flag the module as loaded
    /******/        module.loaded = 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;
    
    /******/    // __webpack_public_path__
    /******/    __webpack_require__.p = "";
    
    /******/    // Load entry module and return exports
    /******/    return __webpack_require__(0);
    /******/ })
    /************************************************************************/
    /******/ ([
    /* 0 */
    /***/ function(module, exports, __webpack_require__) {
    
        var b = __webpack_require__(1);
    
        console.log('a');
    
        b.b1();
    
    
    /***/ },
    /* 1 */
    /***/ function(module, exports) {
    
        exports.b1 = function () {
          console.log('b1')
        };
    
        exports.b2 = function () {
          console.log('b2')
        };
    
    /***/ }
    /******/ ]);
    

    我们看到_webpack_require是模块加载函数,接收模块id

    (对,webpack中每个模块都会有一个独一无二的id,其实也就是在IIFE传参数组中的索引值(0,1,2.....)
    a依赖b,所以在a中调用webpack加载模块的函数

    // 1是模块b的id
    var b = __webpack_require__(1);
    

    上面是使用的commonjs规范书写的
    webpack2是如何对实现es6 modules的
    webpack模块化原理-ES module

    无论什么模块规范书写。我们的webpack进行识别后打包的内容不会相差很多,webpack有优秀的语法分析能力,支持 CommonJs  AMD 等规范。
    webpack为什么能把任何形式的资源都视作模块呢?因为loader机制。不同的资源采用不同的loader进行转换。CMD、AMD 、import、css 、等都有相应的loader去进行转换。那为什么我们平时写的es6的模块机制,不用增加import的loader呢。因为我们使用了babel把import转换成了require。并且Webpack 2 将增加对 ES6 模块的原生支持并且混用 ES6、AMD 和 CommonJS 模块。这意味着 Webpack 现在可以识别 import 和 export 了,不需要先把它们转换成 CommonJS 模块的格式:Webpack 2 有哪些新东西webpack对于es模块的实现,也是基于自己实现的webpack_requirewebpack_exports ,装换成类似于commonjs的形式。es6 module是静态的依赖,所以在运行前进行代码转换,

    这里的实现是将所有导出项作为一个对象的属性,在入口文件执行时,去递归的加载模块。

    如何实现一个简单的webpack

    1. 读取文件分析模块依赖
    2. 对模块进行解析执行(深度遍历)
    3. 针对不同的模块使用相应的loader
    4. 编译模块,生成抽象语法树AST。
    5. 循环遍历AST树,拼接输出js。

     

    1. webpack 源码解析
    2. 细说 webpack 之流程篇
    3. 如何实现一个简单的webpack

    loader原理

    在解析对于文件,会自动去调用响应的loaderloader 本质上是一个函数,输入参数是一个字符串,输出参数也是一个字符串。当然,输出的参数会被当成是 JS 代码,从而被 esprima 解析成 AST,触发进一步的依赖解析。webpack会按照从右到左的顺序执行loader。
    Ast语法树详解  https://segmentfault.com/a/1190000016231512?utm_source=tag-newest
    转自作者:lawpachi

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,064
精华内容 425
关键字:

webpack打包原理