00-认识webpack - 为什么要模块化 -webpack打包过程
webpack在不进行任何配置的情况下,他只认识js。
为什么要打包?
因为一个个小文件,我们合成一个,这样请求就只请求一次。
webpack除了打包之外,还具有翻译官的功能?
loader把浏览器看不懂的代码翻译成浏览器看的懂的代码。
Plugin?
对文件做点别的事情
不管是loader 还是 plugin 都是可插拔,意思就是你什么时候想用,你就装进来,不想用,删掉。所以说webpack不仅强大,而且灵活。
为什么要模块化?模块化的好处?
如上图,传统的一个页面去引入不同的js就是如上一个个去引入,但是这样会有命名冲突的问题,A.js 和B.js中可能有相同的变量命名。
解决方法:
在A.js中和B.js 中加上命名空间。
命名空间会造成一些问题:
如上图,把这个autoLogin命名空间的模块暴露出去了,其实暴露的只是想让login 给别人用,但是全部都给别人了,如果别人误操作去 autoLogin.username = '张三', 不小心把username给改掉了,那么可能你login方法里去做的登录名和密码就永远也不符合了,这不符合开闭原则。
所以,单纯使用命名空间只是为了起到被覆盖,冲突的作用,但是并不能保证随意的访问和篡改,那么如何做呢?
我们用函数作用域,函数的闭包机制,保护里面的变量不被污染。也叫作模块作用域:暴露该暴露的,隐藏该隐藏的。
如上图:这样利用闭包就保护了私有变量,又能只暴露我想暴露出去的这个方法。这样外面再去 :
就拿不到里面的变量了。就不会被人篡改了。这就是所谓的开闭原则
改写一个比较标准的模块化写法:
上面的为什么要用一个对象包裹一下tell方法?不能直接赋值给susanModule吗?
如图以上对比:就是给susanModule 让其为一个对象,对象是叫做tell,tell是个与value同名的key,以后调用的时候就是 susanModule.tell()
综上:我们就可以得到模块化的优点:
1.作用域的封装 :模块内部的实现不会暴露在危险的全局作用域中,上面就是通过暴露tell接口,供外面使用。
2.重用性:如上面的,只需要执行susanModule.tell 就可以拿到这个方法
3.解除耦合 :如果把代码全部扔在一个文件中,出现BUG排查起来很难找,这样模块化后就容易找到定位到错误的模块。
webpack打包原理和过程:
1.把你写的模块(js文件)中的每个逻辑代码块当做webpack一个自执行函数的入参(入参是一个数组,你写的这些代码逻辑块都会装到这个数组中)
第一步:
第二步:把模块包装起来放入自执行函数中的数组(数组都是模块的入参)
第三步:实现模块加载的方法,并把它放到模块执行的环境中,确保模块间可以相互调用。
1.首选去检查,你现在塞给我的这个模块啊我是不是已经加载过了,我去已加载模块的对象中去查这个id,发现已经加载过了,就不进行二次加载了,就直接把加载过的这个结果给你返回过来。
2.如果这个模块没有加载过,那我把其存到那个已加载的对象中,存的时候添加一个moduleId属性,就是给其做个记录
3.接着我就把他的this指到module.exports的导出结果上去,并且去执行已经包装好的模块逻辑。这一步就是让模块逻辑进行执行
4.最后把模块的返回值给return 出去。
第四步:把执行入口文件的逻辑放在一个函数表达式中,并立即执行这个函数(只的就是下面的这个外层的自执行函数)