你一块,我一块——Web-modules 前端模块化
最后更新于
最后更新于
模块化的开发方式可以提高代码的服用效率,方便进行代码的管理。模块化主要体现的是一种分而治之的思想。分而治之是复杂系统开发和维护的基石,模块化则是前段最流行的分治阶段。
具有相同属性和行为的事物的集合,在前端中,将一些属性比较类似和行为比较类似的内容放在同一个 JS 文件里面,把这个 JS 文件称为一个模块,为了每个 JS 文件只关注自身有关的事情,让每个 JS 文件各行其职
模块化要有几个特点:独立,完整,依赖关系
在最开始的阶段,JS 并没有模块化机制,各种 JS 到处飞,也就是所谓的野生代码,得不到妥善的管理。后来前端圈开始制定规范,最耳熟能详的是CommonJS
和AMD
。**node.js
**就是CommonJS
规范的产物。但是由于CommonJS
同步加载更适合服务端,所以迫切需要一个关于客户端的规范,既又出现了很多客户端,耳熟能详的AMD
函数
对象的写法
匿名函数、返回对象
以来传入实参
以上缺点依赖关系不好处理,需要按顺序加载,可能会阻塞页面
立即执行函数,不暴露私有成员
避免命名冲突
更好的分离,按需加载
更高复用性
高可维护性
根据CommonJS
规范,每一个文件就是一个模块,其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。
该规范最初是用来服务器端的 node,前端的 Webpack 也是对 CommonJS 原生支持
CommonJS
的核心思想就是通过 require
方法来同步加载所要依赖的其他模块,然后通过 exports
或者 mode.exports
来导出需要暴露的接口
所有代码都运行在模块作用域,不会污染全局作用域
模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存
模块加载的顺序,按照其在代码中出现的顺序
require
命令的基本功能是,读取并执行一个 JavaScript 文件,然后返回该模块的 exports 对象。如果没有发现指定模块,会报错!
CommonJS
模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块的内部变化就影响不到这个值
上面的代码说明,当module.js
中的值被输出之后,模块内部的变化已经就影响不到这个值了。这是因为 counter 是一个原始类型值,会被缓存。除非写成一个函数,才能得到内部变动的值
注意: 浏览器不兼容 CommonJS
,原因是浏览器缺少 module
、exports
、require
、global
四个环境变量。如要使用需要工具转换。
CommonJS 采用同步加载不同模块文件,适用于服务端 因为模块文件都存放在服务器的各个硬盘上,读取加载时间快,适合服务端,不适应浏览器
CommonJS 为服务器端而生,采用的同步加载方式。因此不适用与浏览器。因为浏览器需要到服务器加载文件,请求时间远大于本机读取时间,倘若文件较多,网络迟缓就会导致页面瘫痪,所以浏览器更希望能够实现异步加载的方式。
AMD 规范是实现异步加载模块,允许指定回调函数,等模块异步加载完成后即可调用回调函数。
AMD 的核心思想就是通过 define
来定义一个模块,然后使用 require
来加载一个模块
AMD 模块定义的方法非常清晰,不污染全局环境,能够清除的显示依赖关系。AMD 模式可以用于浏览器环境,并且允许非同步加载模块,也可以根据需要动态加载模块。
CMD 异步加载,跟 AMD 的主要区别在于,AMD 依赖前置,提前加载依赖。而 CMD 就近加载,按需加载。
CMD 的核心思想就是通过 define 来定义一个模块,然后使用 require 来加载一个模块。
ES6 自带模块化,可以使用 import
关键字引入模块,通过 export 关键字导出模块,功能较之前的几个方案更为强大,也是我们所推崇的,但是 ES6 目前无法在浏览器中执行,所以,我们只能通过 babel 将不被支持的 import 编译为当前受到广泛支持的 require
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用
CommonJS 模块是运行时加载,ES6 模块是编译时输出接口
ES6 模块是动态引用的,并且不会缓存值,模块里边的变量绑定其所在的模块
CommonJS 规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境中使用,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了 AMD 和 CMD 解决方案
AMD 规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过 AMD 规范开发成本高,代码的阅读和书写比较困难,模块定义的方式语义不顺畅
CMD 规范与 AMD 规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在 Node.js 中运行。不过,依赖 SPM 打包,模块的加载逻辑偏重
ES6 在语言标准层面上,实现模块功能,而且实现的相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案