当前位置: 移动技术网 > IT编程>开发语言>JavaScript > webpack笔记( 四 )- 编译结果分析

webpack笔记( 四 )- 编译结果分析

2020年07月24日  | 移动技术网IT编程  | 我要评论

我们每一次用webpack打包以后都会生成一个dist文件夹, 下面有一个main.js文件,我们是时候关注一下webpack的编译结果main.js都写了什么

我们不看main.js到底写了什么, 我们在src目录下新建一个a.js, b.js和index.js, 各自书写代码如下

// a.js
console.log('i am a.js');
module.exports = {
    a: 10,
    b: 20
}
// index.js
console.log('i am index.js');
const result = require('./a');
console.log(result.b);

然后我们想一想, 我们能不能自己写一个dist/myMain.js出来然后实现跟webpack一样的功能呢? 然后咱再去看看webpack是怎么写的, 就很nice

OK, 咱在src下新建一个dist目录, 创建一个myMain.js, webpack做了什么呢, 他根据入口文件分析出入口文件与其他文件之间的依赖关系, 然后将这些文件合并成一个文件, 我们的入口文件就是index.js( 默认就会找index.js ), 而index.js依赖了a.js

// main.js

// 所以我们是要合并./src/index.js 和 ./src/a.js模块, 合并的结果里就是一个普普通通的JS代码, 不再存在任何的模块化代码

// 我们将模块都放进一个对象里这么来写

const modules = {

    './src/a.js': (module, exports, require) => {
        console.log('i am a.js');
        module.exports = {
            a: 10,
            b: 20
        }
    },

    './src/index.js': (module, exports, require) => {
        console.log('i am index.js');
        const result = require('./src/a.js'); // 引入进来的时候这个src路径会被webpack用工具替换一下, 我们就手工修改了
        console.log(result.b);
    }
}

因为webpack会用一个工具方法来找到所有通过requireimport等关键字导入导出的代码, 从而找到他们依赖的模块, 最终将这些模块放在一个对象里, 对象的key为模块的路径名, 对象value为模块文件中的JS代码, 为甚要这样写?

  1. 路径作为key值非常的合适他一定是唯一的, 一个路径对应一个js文件代码, 我们用数组也好, 用其他数据结构也好都不太合适, 当然ES6的新数据结构还是可以做到, 但是对象这么普遍可读性可维护性高啊

  2. 你知道的, 模块化代码最大的优势之一就是代码不会影响任何外部变量, 我们将每个模块化的代码锁死在一个函数里, 不同的函数作用域中变量互相独立互不影响, 这就是为什么模块文件的代码要写进一个函数的原因

  3. 我们必须将module, exports, 和require传入给每个模块函数, 当然这些由我们自己构造, 如果你考虑ES6和其他模块化规范的话, 也是要处理其他规范的, 我们这里只处理commonjs规范了

我们这个对象现在也暴露在了全局下, 就显得非常的不安全, 所以大家能够想到的最常见的就是用立即执行函数封闭作用域

(function() {

    var modules = {
        ...
    }

}())

上面这样写可以吗? 很显然是不可以的, 这个modules对象在每一次打包的时候都是不同的, 怎么能够包在里面呢? 但是有同学说, 不包在里面怎么办鸭, 那不是没办法封闭了, 你看我给你这样写

(function(modules) {

    // 这里面是不是就可以使用modules了


}({ 
    // 咱给他直接通过对象的形式写道这
   './src/a.js': (module, exports = module.exports, require) => {
        console.log('i am a.js');
        module.exports = {
            a: 10,
            b: 20
        }
    },


    './src/index.js': (module, exports = module.exports, require) => {
        console.log('i am index.js');
        const result = require('./a');
        console.log(result.b);
    } 
}))

OK, 我们在这个立即执行函数里, 必须要执行入口函数, 这个没什么好说的吧, 那怎么执行呢? 直接通过require不就执行了吗, 所以我们必须要先提供require方法出来, 然后执行index.js

(function(modules) {

    // 运行一个模块, 得到模块的导出结果, moduleId: 就是每一个函数的path
    function require(moduleId) {
        // 通过moduleId我们是一定要去传入进来的modules里面找到对应的函数执行的, 这些函数必须要接收三个参数, 我们需要构造给他们
        let module = {
            exports: {

            }
        };

       modules[moduleId](module, module.exports, require); // 这个函数一走完, module.exports就有了值了就是模块的导出结果

       return module.exports; // 最后将module.exports丢出去
    }

    require('./src/index.js');

}({
    ...
}))

我们还知道, webpack是会对模块进行缓存的, 多次引入同一个模块其实都是引入的第一个, 所以我们也要处理一下

(function(modules) {

    const moduleCache = {}; // 模块缓存池

    function require(moduleId) {

        //这里在require的时候要先看一下moduleCache中有无数据
        if(moduleCache[moduleId]) {
            return moduleCache[moduleId];
        }

       let module = {...};

       modules[moduleId](module, module.exports, require); 

       // 我们在这里要加一行代码
       moduleCache[moduleId] = module.exports;

       return module.exports; 
    }

    require('./src/index.js');

}({
    ...
}))

这个时候我们的myMain.js就写完了, 我们来执行以下这个js看看效果是不是如我们所愿

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vRbnQxwg-1595381919708)(./blogImags/runMyMain.png)]

我们会发现确实执行结果是按照我们预期的执行了, 所以基本上webpack内部编译以后形成的编译结果也就是我们这样了。 这就是webpack的编译结果分析, 希望可以对你后续的学习产生帮助

本文地址:https://blog.csdn.net/weixin_44238796/article/details/107505123

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网