一、模块化概述
1.1. 什么是模块化?
- 将程序文件依据一定规则拆分成多个文件,这种编码方式就是模块化的编码方式。
- 拆分出来每个文件就是一个模块,模块中的数据都是私有的,模块之间互相隔离。
- 同时也能通过一些手段,可以把模块内的指定数据“交出去”,供其他模块使用。
1.2. 为什么需要模块化?
随着应用的复杂度越来越高,其代码量和文件数量都会急剧增加,会逐渐引发以下问题:
1.全局污染问题
2.依赖混乱问题
3.数据安全问题
二、导入与导出的概念
模块化的核心思想就是:模块之间是隔离的,通过导入和导出进行数据和功能的共享。
导出(暴露):模块公开其内部的一部 (如变量, 函数等),使这些内容可以被其他模块使用。
导入(引入):模块引用和使用其他模块导出的内容,以重用代码和功能。
三、模块化实例
1.创建School.js
2.创建Student.js
3.创建index.js
4.导出数据
导出数据的方式有两种
-
第一种方式:module.exports = value
-
第二种方式:exports.name = value
5.导入数据
使用内置的request模块导入数据
四、规范
1.CommonJS
CommonJS是一种面向服务器端的模块化规范,它规定一个文件就是一个模块,使用require()导入模块,使用module.exports导出模块。
var moduleB = require('./moduleB');
module.exports = {
stuff: moduleB.doStuff();
};
require()的返回值就是module.exports导出的对象。
-
缓存加载 首次require一个模块时,会加载并执行该模块文件,并返回模块的module.exports值,该值会被缓存。下次require该模块时,取的是缓存数据,不需要再加载执行模块了。
-
拷贝导出 require()返回的是模块导出对象的拷贝,也就是说,模块内部的变化不会影响已导出的对象。
-
同步加载 CommonJS使用同步加载,这并不适用浏览器端,因为网络延迟会阻塞页面渲染。
-
浏览器加载CommonJS npm模块是遵循CommonJS的,不能直接在浏览器运行,需要做格式转换。
小结
CommonJS规定每个文件是一个模块,使用require()导入模块,使用module.exports导出模块。其中,还使用了缓存加载和拷贝导出。
CommonJS使用同步加载,这不适用浏览器,因为网络延迟会阻塞页面渲染。
npm模块是遵循CommonJS的,不能直接在浏览器运行,需要做格式转换。
2.AMD
AMD是一种面向浏览器端的模块化规范,使用异步加载,并在依赖加载后再回调执行入口模块。
定义模块:
define('moduleA', ['moduleB', 'moduleC'], function factory(moduleB, moduleC){
let nameB = moduleB.getName();
let nameC = moduleC.getName();
let name = nameB + nameC;
return {
getName: function(){
return name;
}
}
})
define()的第一个参数是模块标识符。第二个参数是依赖。第三个参数是模块工厂函数,用来封装模块。
导入模块:
require( ['moduleB', 'moduleC'], function main(moduleB, moduleC){
let nameB = moduleB.getName();
let nameC = moduleC.getName();
let name = nameB + nameC;
console.log(name);
})
3.ES6 Module
ES6 Module是JavaScript语言标准的模块化方案,浏览器和node环境都是原生支持的,不需要格式转换。
1.ES6 Module加载模块
在ES6 Module中使用import导入模块,使用export导出模块。
import moduleA from 'moduleA'
export default {
name:'moduleB'
}
在编译阶段,根据import/export构建模块依赖关系,即模块地图sourceMap,每个节点保存了模块导出变量的内存地址和模块加载状态。
在运行阶段,执行模块时先更新节点的模块加载状态,遇到import时,则从模块地图中获取到对应模块导出变量的内存地址。
2.浏览器加载ES6 Module
<script type="module">
</script>
<script type="module" src="module path"></script>
在 script中设置type="module"属性,浏览器就会当作模块处理,而不是普通的脚本文件。
script type=“module”跟script defer一样使用异步加载,然后延迟到文档解析完成后再按顺序执行脚本。
五、总结
随着用户体验要求变高,前端承载的功能变多了,代码量也随着膨胀。
为了提高代码的可复用性,开发者采用了模块化思想并利用JavaScript语言特性进行模块化实践,包括命名空间,函数作用域,闭包等。
同时,诞生了CommonJS,AMD和ES6 Module等模块化规范。其中,前两者是社区版本的,分别是面向服务器端和浏览器端的规范。而ES6 Module是JavaScript语言标准,将会逐步成为统一的模块化规范。