以前对这几个概念一直记得很模糊,也没法用本身的语言表达出来,今天看了大神的文章,尝试根据本身的理解总结一下,算是一篇读后感。javascript
大神的文章:http://www.css88.com/archives/7628
(大神的文章写的很详细,建议先看完大神的文章)css
什么是js模块化,咱们从历史提及。html
1.一开始咱们怎么写脚本?就是在html文件中用<script></script>写代码java
这种方式的缺点:代码复用靠复制,基本是全局变量。webpack
2.后来咱们用js文件写代码,用<script></script>的src引入html,html/css/js分离es6
这种方式的缺点:web
代码虽然可复用,可是<script></script>愈来愈多,一个html文件加载了好多js(http请求过多,影响性能),浏览器
全局变量也多,依赖关系也愈来愈复制,好比b依赖a,则a文件必定要在b文件以前加载服务器
(这种方式的问题就是全局变量过多和依赖关系复杂)异步
3.为了解决全局对象的问题,咱们进化到第三个阶段,用模块对象和IIFE(当即执行函数)
这种方式的缺点:
虽然暴露的全局变量少了,只有这一个模块对象,能够说解决了污染全局变量的问题,可是依赖关系还没解决,由于IIFE依赖这个模块对象进行各个文件的操做,就是说导入导出都靠这个模块对象。
(这个时候已经实现了js模块化,每一个文件都包在匿名函数中,因此说每一个文件都是一个模块,模块与模块之间的调用经过这个全局模块对象,这个时候的问题是,全局变量少了,可是依赖模块没解决,全部的js文件都依赖全局模块对象,就是说这个全局模块对象要在其余js文件以前引入,因此说咱们下个方案就是解决依赖关系)
新的模块化方案提出:解决了全局变量和依赖关系的问题,可是性能方面还能够优化。
commonJS规范的提出,让人们有了新的方案来解决全局变量污染和依赖关系复杂这两个问题。(一开始是运行在服务器端)。先让咱们了解下什么是commonJS。
commonJS是一个规范,不是一个库,他提出了模块化方案,定义了一个模块化的API,让咱们写出模块化的js更容易,再也不须要借助IIFE。
用法:在一个js文件中,用export导出变量,用require导入
//a.js var a=1; module.exports=a; //b.js var a=require(/a.js);
这种方式在服务器端运行良好
可是有个问题,这种方式是同步运行的,俗称CMD(同步模块定义),(固然服务器端去读取文件特别快,没这个问题,不像浏览器端还要发请求去获取),就是说当b.js在require(a.js)时,这个时候js代码不会去往下执行,他必须等到a.js加载完才能够,若是a.js文件特别大,那么页面就会卡死,为何?(由于commonJS是同步运行的,而js又是单线程的,会阻塞js文件的渲染),因此说浏览器端不能用这种方案,,因此commonJS提出了AMD(异步模块定义),就是获取文件是异步的,规范提出来了,可是在浏览器怎么实现?业内大神造出了轮子,用的多的就是require.js和sea.js
RequireJS 和 SeaJS 是模块加载器
利用模块加载器,咱们只有一个入口文件,而后根据依赖关系去加载对应的js文件,依赖关系在入口文件写好,(只有一个入口文件,可是解析依赖关系的时候会去加载对应的依赖模块,加载的js文件就不止一个了)
二者的区别:
1.二者都是异步加载js,只不过一个写法遵循amd,一个写法遵循cmd,其实都是让浏览器支持模块化写法的库。
2.requirejs是不管模块需不须要都去加载彻底部的依赖文件,seajs是某个模块须要用到才去加载,因此说AMD体验好,由于依赖模块一开始全都加载好了,cmd性能好,由于须要才去加载对应的模块
这样咱们就能够在浏览器端实现模块化开发了,解决了全局变量的问题,也解决了依赖关系的问题,可是却也带来了新的问题,页面依赖的文件多(浏览器解析的时候就会去加载对应的依赖模块,一个模块就是一个文件),发起的http请求也多,随之而来的就是加载性能的影响(HTTP1,并行的http请求有限制个数).这个时候模块打包器就应运而生了.
在模块化加载器处理的基础上,为了减小解析时加载依赖模块而增长的http请求,咱们能够把入口文件打包,在打包的过程当中,让它去加载对应的依赖模块,最终生成的那份文件就是包含依赖模块的文件,那样就能够减小http请求,这样的打包操做咱们交给构建工具或者说打包工具去实现,好比webpack/Browserify/rollup等等,这样,咱们能够只专一怎么写出模块化的,可维护的,高聚合,低耦合的代码
随着es6的出现,js原生也出现了模块开发定义,也有对应的规范,用export导出,用import导入,让咱们能够不用使用requirejs和seajs就能进行模块化开发,不过目前浏览器兼容性有限,不过咱们能够用webpack来实现兼容,webpack不仅能够帮咱们把相关依赖的文件打成一个包,也能帮咱们打成一个可以兼容的包(借助一些loader).
欢迎交流~