模块化可以说是目前前端最重要的开发范式之一,模块化是一种思想,这种思想,在不同的前端开发阶段,其实现的方式也各不相同文件划分方式
起初前端通过文件划分的方式来实现模块化,如分别定义a.js文件和b.js文件,每个文件中有相关的逻辑的变量,然后在html中统一引入
这种方式有很大的缺陷【前端工程化|前端模块化的演变】首先就是全局变量的问题,引入的各个文件都将把各自的变量挂载到全局,各个文件间的变量命名也可能会有冲突,而且各个文件之间可能会有依赖关系,难以管理。
命名空间方式
这种方式对文件划分的方式进行了改进,针对每一个文件,定义一个全局的类,所有的变量和函数均写在这个类里面,这样在引入的时候就可以解决各个模块之间命名冲突的问题。但是,可以看到,即使这样,依然可以从全局去访问或修改每个模块下的成员,模块的依赖关系也没有办法解决。
var moduleA = {
name:'module-a',
method1:function(){}
}
自执行函数的方式
自执行函数通过单个文件中定义自执行函数,然后运行函数将方法挂载到全局,这样实现私有变量的形式,使得全局无法直接访问到单个模块的变量,只能通过闭包的方式去方法,并且可以通过传参的形式,来解决模块间的依赖。
(function($){
var modulea = 'module_a'
function method1(){
console.log(modulea)
}
function method2(){
console.log('sx'+modulea)
}
window.moduleA = {
method1:method1,
method2:method2
}
})(jQuery)
以上的方式是在前端构建工具,模块化范式没有出现之前的的模块化实现方式,这种方式的引入顺序依靠约定实现,且通过script标签方式引入,在后期代码维护方法会产生很大的干扰,后来,有人开始尝试利用js来实现一种模块化规范,因此实现模块的定义、引入。commonjs规范
commonjs是node中提出的规范,其所规定有:
- 一个文件就是一个模块
- 每个模块都有单独的作用域
- 通过module.exports导出成员
- 通过require函数载入模块
但是这种规范并不适合浏览器端,因为commonjs是同步执行的,在node中只需在node启动的时候即可加载好所有模块,但是这种方式在浏览器端,则会产生很大的负担,在网页每次刷新的时候,浏览器都需要进行大量同步请求,对于其性能的影响很大。AMD规范
为解决这种方式,浏览器端也产生了AMD规范,并产生了相关的库-require.js
这种方式通过定义模块和引入模块机制,内部自动生成script标签,引入相关的内容
//定义模块
// 参数:1.模块名,2.模块依赖项,3.自定义模块
define('module1',['jquery','./module2'],function($,module2){
return {
start:function(){
$('body').animate({
margin:'200px'
module2()
})
}
}
})//载入模块
require(['module1'],function(module1){
module1.start()
})
但是这种方式本质上也是通过动态创建script标签实现模块的引入,在实际代码中,需要频繁创建和引入模块的时候,对浏览器的开销很大。esmodule
es6出现之后,在浏览器端总结之前的规范,设计了esmodule规范,且目前已被大多数浏览器兼容,目前,浏览器端基本由esmodule规范占据大半,而node端则是commonjs规范