Mode配置
之前我们打包的时候一直报错,mode属性没有设置。看下基本配置

mode错误
在官网这里可以查到相关信息。
mode可以有三个取值,development production(默认) none
我们默认是设置为production,生产模式,顾名思义要上线了,为了性能优化,要压缩,所以webpack会进行丑化。
当我们设置为development时,会开发模式,开发模式暂时不上线所以无需丑化。
打包后
可以看到就是正常的js文件没有被压缩过。
这三个取值的含义以及不同取值的结果


每个取值其实都做了很多事情,目前只需了解他是干嘛的,还不用关系里面的具体。
模块化原理
webpack允许我们使用各种各样的模块化,如ES MODULE(ES6) COMMONJS(node)等
但浏览器默认不支持commonjs,es6模块化有些旧的浏览器也不支持。但是webpack里面我们可以随便写。那么webpack怎么支持模块化呢?
我们研究四个原理:
Commonjs模块化实现原理
ES Moduls实现原理
commnjs加载ES module的原理(es module导出commonjs导入)
es module加载commonjs的原理
1 commonjs模块化实现原理


代码很简单,方便理解。
可以看到很多代码很杂,把devtool设位source-map设置就好,后期再具体再了解其用途

可以看到代码已经整洁多了。
再把注释删掉,可以看到已经很整齐了。
接着来看下代码。立即执行函数

这里放着的使我们得以一个个模块,因为现在只有一个模块,所以只有一个值。
再定义一个对象作为模块的缓存,如果加载过的就去缓存的值。
然后定义一个函数,当我们加载模块,就是从模块导出的东西取取值的时候,就通过这个函数的,
最后一个
这其实也是立即执行函数,可以看到我们的执行的代码实在这面的,可以看出也是通过require引入,只不过用的是webpack自己定义的函数引入。
现在看不懂没关系,理一下逻辑。
运行代码时,执行,
传入路劲,
走到我们自定i的函数,判断是否有缓存,有的话直接返回缓存的exprorts,
没有的话,放入缓存之中,定义为一个对象。然后赋值给module。最后

可以很明显看到直接调用了一开始创建用来放模块的对象。然后通过路径找到该函数,然后将module传进去。后面两个干嘛呢,刚我们的文件引用一个模块,然后里面又引用一个模块的话,这两个就有用了。现在只有一个暂时不用管他。
所以现在就相当于
执行了这个函数,值为{exports: {}}
然后给他赋值,赋的值
也就是说我们现在的module里的exports已经是这个函数了。
然后return回去,
然后传给num,再执行,
这样就完成模块化了。
捋一下思路,webpack帮助我们对commonjs的模块化导出,打包成一个Bundl.js文件,她做了什么事呢?首先生成一个对象,这个对象有几个属性,属性名就是我们的模块路劲,属性值是什么呢?就是我们导出的东西,可能是一个函数也可能是一个值。第二步,内部定义一个对象,这个对象存放着所有加载过的模块的缓存。第三步,内部定义一个函数,这个函数就是用来处理我们记载模块的。第四步,就是使用立即指向函数,通过第三步定义的函数,取到我们实际上导出来的值或者函数,然后再直接调用。
关键就是这个第三步,webpack会把路径传进去,然后通过这个路劲,先看缓存有没有值,没有的话,直接加入缓存去,然后再定义一个module对象,里面有个export属性,最后再通过我们第一步创建的对象,去拿到我们对应的值,这个值接受一个参数Module,就是我们顶一个那个Module对象传进去,然后通过给module.exports赋值,就把我们导出的函数赋值到上面,然后再return回去。第四步拿到函数返回来的值后,就立即执行调用,达到一个模块化的效果。第四步还可以传入两个参数,module.exports和第三步的函数,为的就是当引入的模块内部还有引入其他模块时,可以做处理,现在只有一层,所以姑且不管。
模块化其实也就是为了防止命名空间错乱,这里面的底层思想主要也是运用了函数作用域,实现了类似于模块化得效果。




大体流程就是这样,可以自己去看看,很简单。
es module




代码有点多,但其实逻辑差不多,一步一步看。
第一步,还是一个对象。用路劲作为属性名,
第二步,缓存,看到Cache就知道了是个缓存。
第三步 加载模块的实现,跟common.js一摸一样
第四步,立即执行函数。这个执行函数是给我们第三步的执行函数添加一个属性r,这个r就是一个函数。这个d我们猜想就是判断是esModule还是module,因为他给我们的exports添加了属性。值设位_esModule或者symbol.toStringTag,值为Module。所以这个r函数就是Module和__esModule。
第五步
开始执行代码了。
先调用r函数,给我们的第一部创建的对象做标记,证明是_esmodule。
然后调用我们的第三步的函数来加载模块。
然后又会调用第一步的对象里面的函数
这时候里面的操作注意了,跟之前的不太一样,
这时候的module.export就是上图那样然后被第三部的函数return回去。
拿到后调用exprots里面的default属性的值,也就是我们导出来的函数,然后执行。
里面用到了(0,fun)(a,b)其实这个跟直接fun(a,b)效果一样的。
捋一下思路,esModule与commonjs类似,但是多了一个r函数,这个函数是用来标记对象里面的一个属性,标记是否是__esModule。其他步骤与commonjs类似。
但其实我们导出了一个所以webpack默认给我们的exports对象加了个default属性,那要是两个呢?


打包后



可以看到,其实只多了第三幅图
多了这个d函数,跟这个o函数。先看看o函数
obj去调用这个hasOwnProperty,然后判断Porps是不是自身的属性。
再看看D
d做的事情稍微复杂一点,但仔细看,d就是遍历第二个参数,判断条件就可以看出来,是判断属性是不是自身的,或者是exports上面没有的,才会继续往下走。
往下走干嘛呢,get?似曾相识啊,这不是做代理吗。给exports对象加上key属性,然后取出的值却是definiton[key]。典型做代理呀。这个其实就是在exprots上面设置属性key,然后外面拿到这个值的真实值是definition[key],也就是exports.key = definition[key]。
了解两个用法后我们再看看怎么调用。

然后第三部函数最后一步调用这个对象

这里的执行跟上面的也不太一样
执行完r函数,加标记,然后执行代理,第二个参数实际上就是num和Numw,写成函数形式而已,返回的其实是下面const定义的函数和值。经过d后,exports.num export.num2就有值了,因为做了代理。

然后第三部的函数返回module.exports对象,
与其说是e’xpots里面有值了,不如说是做代理了。