前端模块化

100 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第7天,点击查看活动详情

JavaScript 模块化发展史

第一阶段

在 JavaScript 语言刚刚诞生的时候,它仅仅用于实现页面中的一些小效果。在这种情况下,语言本身所存在的一些缺陷往往被大家有意的忽略,因为程序的规模实在太小,只要开发人员小心谨慎,往往不会造成什么问题。

第二阶段

ajax的出现,逐渐改变了 JavaScript 在浏览器中扮演的角色。现在,它不仅可以实现小的效果,还可以和服务器之间进行交互,以更好的体验来改变数据。

第三阶段

也是从此刻开始,人们认识到,JS(ES)是一门真正的语言,它依附于运行环境(运行时)(宿主程序)而执行。 nodejs的诞生,便把JS中的最后一个问题放到了台前,即全局变量污染和依赖混乱问题。
要直到,nodejs是服务器端,如果不解决这个问题,分模块开发就无从实现,而模块化开发是所有后端程序必不可少的内容。
最终,形成了一个模块化方案,即CommonJS,该方案,彻底解决了全局变量污染和依赖混乱的问题。

第四阶段

CommonJS的出现打开了前端开发者的思路,既然后端可以使用模块化的JS。开始有人想办法把CommonJS运用到浏览器中。
于是很快,AMD规范出炉,它解决的问题和CommonJS一样,但是可以更好的适应浏览器环境相继的,CMD规范出炉,它对AMD规范进行了改进。
ES6发布,它提出了官方的模块化解决方案 —— ES6 模块化
从此以后,模块化成为了JS本身特有的性质,这门语言终于有了和其他语言较量的资本,成为了可以编写大型应用的正式语言。

可以看到,模块化的出现,是JS通向大型应用的基石,学习好模块化,变具备了编写大型应用的基本功。

CommonJS

CommonJS使用exports导出模块,require导入模块 具体规范如下:

  1. 如果一个JS文件中存在exportsrequire,该JS文件是一个模块。
  2. 模块内的所有代码均为隐藏代码,包括全局变量、全局函数,这些全局的内容均不应该对全局变量造成任何污染。
  3. 如果一个模块需要暴露一些API提供给外部使用,需要通过exports导出,exports是一个空的对象,你可以为该对象添加任何需要导出的内容。
  4. 如果一个模块需要导入其他模块,通过require实现,require是一个函数,传入模块的路径即可返回该模块导出的整个内容。

AMD

全称是Asynchronous Module Definition,即异步模块加载机制
require.js实现了AMD规范
在AMD中,导入和导出模块的代码,都必须放置在define函数中

define([依赖的模块列表], function(模块名称列表){
    //模块内部的代码
    return 导出的内容
})

CMD

全称是Common Module Definition,公共模块定义规范
sea.js实现了CMD规范
在CMD中,导入和导出模块的代码,都必须放置在define函数中

define(function(require, exports, module){
    //模块内部的代码
})

ES模块化

ECMA组织参考了众多社区模块化标准,终于在2015年,随着ES6发布了官方的模块化标准,后成为ES6模块化
导入通过import,由于使用的是依赖预加载,因此,导入任何其他模块,导入代码必须放置到所有代码之前。
导出通过export,类似于 exports.xxx = xxxx

ES6模块化具有以下的特点

  1. 使用依赖预声明的方式导入模块

    1. 依赖延迟声明

      1. 优点:某些时候可以提高效率
      2. 缺点:无法在一开始确定模块依赖关系(比较模糊)
    2. 依赖预声明

      1. 优点:在一开始可以确定模块依赖关系
      2. 缺点:某些时候效率较低
  2. 灵活的多种导入导出方式

  3. 规范的路径表示法:所有路径必须以./或../开头