1.牢骚
CommonJS, AMD, CMD , 其实很早就接触过了。
当时, 网上的文章看得眼花缭乱, 只依稀记得几个模糊的概念。
什么依赖前置 , 什么按需加载。
一头雾水。
现在再回过头来看看概念 , 网上部分文章用词模棱两可。
给我们这些菜鸡, 带来了理解的偏差和困惑。
记得第一个项目还用了requireJS 。
时过境迁,现在入门前端 , 都是直接上webpack了 。
但我觉得还是有必要理一理 。
2. 是什么
CommonJS, AMD, CMD是规范, 理念 ;
- 对 CommonJS 的实现 , 有 node 的模块系统 ;
- 对 AMD 的实现有require.js ;
- 而 CMD, 是在sea.js的实现中提出来的
(但是在Google和Stack Overflow, 这个概念很少被提到, 一般出现在国内)
。
-
CommonJS规范, 模块加载是同步的
对node来说,模块存放在本地硬盘,同步加载,等待时间就是硬盘的读取时间,这个时间非常短;
-
AMD、CMD 规范,模块加载是异步的
目的, 是为了适应浏览器环境,加载的时间取决于网络的好坏,可能要等很长时间;
3. 先说 async 和 defer
记得看文章的时候, 看到了下面这段话 ,
我看了半天, 总觉得不是很理解 , 为什么呢 ?
这里说, 脚本标签天生是异步的
, 那为什么会出现 async 和 defer ?
然后, 我发觉我并没有把 加载
和执行
的概念区分清楚 , 这里的加载我把它理解为浏览器中的下载
这里贴一张图就很清楚了:
<script>
标签, 在下载和执行的时候 , 会阻塞dom的渲染进程 , 所以如果把<script>
标签放在<head>
中, 当 js 文件很大或者网络差时, 会导致页面长时间空白( 顺带提一下, <script>标签并不会阻止其他的<script>标签的下载, 现代浏览器中多个<script>下载是并行的, 在chrome中, 默认支持6个资源(http1.x)并行下载 )
, 另外 , 脚本是按照<script>
标签的书写顺序执行的 ;<script defer>
在加上defer
以后, 下载的过程就不会阻塞dom渲染了, 但脚本的执行是在dom渲染完毕之后;<script async>
在加上async
以后, 下载的过程同样不会阻塞dom渲染, 但脚本会在下载完后立刻执行, 所以存在多个<script async>
时, 无法保证多个js文件的执行顺序, 加载较快的脚本会执行;
所以defer, async主要作用于加载阶段, 执行阶段仍然会阻塞dom渲染
4. 再看 require.js 的异步体现
再看看使用require.js的模块写法
新建 main.js / a.js / b.js , main.js 为入口, 引用了a.js , b.js
// main.js
// waitSeconds = 0的配置, 是为了防止文件过大或网络不佳时, 加载时间过长导致require报`Load timeout for modules`的错误
require.config({
waitSeconds: 0
});
require(