模块化
服务端模块化
Nodejs出现开创了一个新的纪元,使得我们可以使用javascript写服务器代码,对于服务端而言必然是需要模块化的。
Nodejs和CommonJS的关系
这里要说一下Nodejs和CommonJS的关系。
- Nodejs的模块化能一种成熟的姿态出现离不开CommonJS的规范的影响
- 在服务器端CommonJS能以一种寻常的姿态写进各个公司的项目代码中,离不开Node的优异表现
- Node并非完全按照规范实现,针对模块规范进行了一定的取舍,同时也增加了少许自身特性
CommonJS规范(运行时加载)
对模块的定义非常简单,主要分为模块引用,模块定义和模块标识3部分
- 模块引用,即
require
模块 - 模块定义,module.exports
- 模块标识,require( )函数的参数
Nodejs的模块化实现
Node中一个文件是一个模块——module,一个模块就是一个Module的实例
前端模块化
commonjs不适用于前端
如果我们在某个代码模块里使用CommonJS的方法require了一个模块,而这个模块需要通过http请求从服务器去取,如果网速很慢,而CommonJS又是同步的,所以将阻塞后面代码的执行,从而阻塞浏览器渲染页面,使得页面出现假死状态。
因此后面AMD规范随着RequireJS的推广被提出,异步模块加载,不阻塞后面代码执行的模块引入方式,就是解决了前端模块异步模块加载的问题。
AMD
异步模块加载规范 与CommonJS的主要区别就是异步模块加载,就是模块加载过程中即使require的模块还没有获取到,也不会影响后面代码的执行。
和commonjs都是运行时加载,一个一般用于服务端,一个一般用于浏览器客户端
运行时加载
- CommonJS 和AMD模块都只能在运行时确定模块之间的依赖关系
- require一个模块的时候,模块会先被执行,并返回一个对象,并且这个对象是整体加载的
cmd
与AMD规范的主要区别在于定义模块和依赖引入的部分。AMD需要在声明模块的时候指定所有的依赖,通过形参传递依赖到模块内容中。CMD支持动态引入,require、exports和module通过形参传递给模块,在需要依赖模块时,随时调用require( )引入即可
amd和cmd:
CommonJS是同步加载模块,服务器所有模块都存放在本地,硬盘读取时间很快引入模块化的思想,mudule.exports,require同步,amd:浏览器端模块化,不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数,也就是大名鼎鼎RequireJS。
1、AMD推崇依赖前置,在定义模块的时候就要声明其依赖的模块
2、CMD推崇就近依赖,只有在用到某个模块的时候再去requireAMD在加载模块完成后就会执行改模块,所有模块都加载执行完后会进入require的回调函数,执行主逻辑,这样的效果就是依赖模块的执行顺序和书写顺序不一定一致,看网络速度,哪个先下载下来,哪个先执行,但是主逻辑一定在所有依赖加载完成后才执行
CMD加载完某个依赖模块后并不执行,只是下载而已,在所有依赖模块加载完成后进入主逻辑,遇到require语句的时候才执行对应的模块,这样模块的执行顺序和书写顺序是完全一致的
ES6
commonJs模块和ES6模块
1、CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
2、所谓值的拷贝,原始类型的值被缓存,不随模块内部的改变而改变。
3、ES6 模块是动态引用,不缓存值,模块内外是绑定的,而且是只读引用,不能修改值。ES6 的 js 引擎对脚本静态分析的时候,遇到加载命令模块 import ,就会生成一个只读引用,当真正用到模块里边的值的时候,就会去模块内部去取。
4、CommonJS 模块是运行时加载,ES6 模块是编译时加载输出接口。
5、运行时加载:CommonJS 模块就是对象;是先加载整个模块,生成一个对象,然后再从这个对象上面读取方法,这种加载称为“运行时加载”。
6、编译时加载: ES6模块不是对象,而是通过 export 命令「显式指定输出的代码」。import 时采用静态命令的形式,即在import指定「加载某个输出值」,而「不是加载整个模块」,这种加载称为“编译时加载”。
7、import的接口是read-only(只读状态),不能修改其变量值。 即不能修改其变量的指针指向,但可以改变变量内部指针指向,可以对commonJS对重新赋值(改变指针指向),但是对ES6 Module赋值会编译报错。
ES6 Module和CommonJS模块的共同点:
CommonJS和ES6 Module都可以对引入的对象进行赋值,即对对象内部属性的值进行改变。