模块化标准【AMD】【CMD】【CommonJS】【ES6】以及 module.exports、exports、export、export default、require、import 间的理解概论

一、模块化(原因和概念)

先介绍一下模块化是个什么东西,解决了什么。
模块化概念和分类这个部分转自别人转的,也不知道原博在哪,但是写得很不错,所以拿来分析总结一下。

JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着 web2.0 时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀
这时候JavaScript作为嵌入式的脚本语言的定位动摇了,JavaScript却没有为组织代码提供任何明显帮助,甚至没有类的概念,更不用说模块(module)了,JavaScript极其简单的代码组织规范不足以驾驭如此庞大规模的代码
既然JavaScript不能处理好如此大规模的代码,我们可以借鉴一下其它语言是怎么处理大规模程序设计的,在Java中有一个重要带概念——package,逻辑上相关的代码组织到同一个包内,包内是一个相对独立的王国,不用担心命名冲突什么的,那么外部如果使用呢?直接import对应的package即可import java.util.ArrayList;
遗憾的是JavaScript在设计时定位原因,没有提供类似的功能,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,我们称为模块化。
一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。模块开发需要遵循一定的规范,各行其是就都乱套了

简单来说就是以前前端简单,项目工程也小,现在前端突然发展开来,随之一些需求及项目复杂度也增加,js语言原本的定位不足支持这些工程,就需要向一些成熟的老大哥学习(java等),模块化使代码从一坨变成规整的一块一块。

利于维护(一块出问题了就维护一块)

利于分配工作(每人负责几块)

利于使用(想用哪块的话就拿来哪块)

1、前端模块化的前辈

js模块化有3个最基础的前辈

  1. 函数封装(代码还是一坨)
  2. 向其他语言学习,创建对象(面向对象编程,如果把函数比作能做的事,对象就是做事的人,想要做什么事,就找某个能做这个事的人,而不是去成千上万个事中找。还是一坨。)
  3. 通过<script>标签引入自调用函数包(已经变成块了,不过这个块只能连接一层,块之间的依赖只能手动增添,比如a.js依赖于b.js,然后手动添加script标签,然后b.js又需要依赖c/d/e/f/g/h.js等,也要手动写入,而且要注意写入的先后顺序,而且很多都需要导出一个函数或对象到全局作用域才能使用。)

前面的模块化也适应不了日益增长复杂的前端项目。 这时后端(也就是node.js)迈出了真正模块化的第一步——CommonJS标准

2、CommonJS(同步加载,同步执行)

参考原文中这么写——

因为在网页端没有模块化编程只是页面JavaScript逻辑复杂,但也可以工作下去,在服务器端却一定要有模块,所以虽然JavaScript在web端发展这么多年,第一个流行的模块化规范却由服务器端的JavaScript应用带来,CommonJS规范是由NodeJS发扬光大,这标志着JavaScript模块化编程正式登上舞台。

但是CommonJS的思想并不能用在浏览器上——

模块系统需要同步读取模块文件内容,并编译执行以得到模块接口。
这在服务器端实现很简单,也很自然,然而, 想在浏览器端实现问题却很多。
浏览器端,加载JavaScript最佳、最容易的方式是在document中插入script标签。但脚本标签天生异步,传统CommonJS模块在浏览器环境中无法正常加载。
解决思路之一是,开发一个服务器端组件,对模块代码作静态分析,将模块与它的依赖列表一起返回给浏览器端。 这很好使,但需要服务器安装额外的组件,并因此要调整一系列底层架构。

就是说CommonJS是同步加载的,<script>标签是异步加载的,所以CommonJS的同步加载思想不能用在浏览器端上。

那问题来了,原文有这一句话——但脚本标签天生异步,传统CommonJS模块在浏览器环境中无法正常加载。

<script>标签不是会同步加载和执行并阻塞dom树的构建吗,怎么在他那边就变成异步加载了。
首先我们要先看清楚加载这个词的意思,它在浏览器端指的是下载,在服务器端可以指读取硬盘资源。
同步加载是指在构建dom树时原本就有的一些<script>标签,在前一个标签内容加载和执行完之前,会阻塞dom树的构建,也就是不会开始解析下面<script>标签,也就不会加载此标签的内容了。

但模块化需要的是让每一个模块本身可以自动加载所需依赖。所以肯定得手动用代码去添加<script>标签来加载和执行其中所带的代码段。

但是手动添加的<script>标签它就是异步下载的,也就是我想同时想要下载a、b两个依赖,它们会同时下载,而不是和CommonJS中的那样先下载完a再下载完b,而且如果浏览器端同步加载的话,因为网络下载的延迟性,会阻塞浏览器页面的显示。所以说环境和框架不同使用的标准也要有变化。

于是requireJSseaJS两个模块化工具出现了,随之而来的是requireJSseaJS分别衍生出来的两个标准AMDCMD

3、AMD(异步加载,异步执行)

AMD为前端JS制定了规范,它使用异步的方式去加载模块,并且所有与模块相关的代码都写在回调函数当中,不影响其他代码的执行。
它主张依赖提前,就是在开始便异步加载所有依赖,哪个依赖先加载完就先执行。不过主逻辑还是同步的等所有依赖加载完后再执行。
相对于使用自调用函数封装并用<script>标签导入来说,它解决了:

  1. 异步加载,不会阻塞浏览器构造dom树
  2. 自动加载依赖,不再需要手动引入模块间的依赖关系
    目前requireJScurlJS为这个标准的主要实现

4、CMD(异步加载,同步执行)

CMD是淘宝团队开发的SeaJS在推广过程中的产出,弥补了AMD的一大缺点——异步执行,由于AMD是异步加载,并且加载完直接执行,所以执行的顺序与加载速度有关,并且不可控,这就非常不友好,于是CMD提倡的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值