webpack打包原理

302 阅读2分钟

webpack打包原理

上节《浅谈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打包原理的简化版。

结束语:

前端技术博大精深,笔者才学疏浅,上述所述均为自身观点,而非标准答案。

| 笔者: DinosaurCoder