coolie入门2-模块化与模块化加载
1、模块化
在前端开发中,模块化是趋势,毋庸置疑。尤其是单页面程序中,当然还涉及到模块的生命周期等,这些另说。完善的前端模块化规范来的非常的晚,在之前,各种后端开发早已实现这些基础问题,唯独前端一直没有得到良好的解决。与前端的运行环境、异步加载等因素有关。
目前主流的模块化规范是 AMD、CMD、CommonJS 这些,coolie
支持的是 CMD 规范。先看下 CMD 规范是怎么样的:
define(function(require, exports, module){
// 引用相对于当前模块路径的 path/to/file.js
var a = require('./path/to/file.js');
// todo
});
注意点:
- 每个模块都需要
define
包裹,主要原因是避免全局污染,并且利于静态分析依赖。 require
字面量,不能被修改为其他值,因为模块加载器是通过正则分析require
关键字的。require
路径必须为相对或者绝对路径,路径再长也没关系,在构建之后路径会被计算成单个字符。- 一个文件仅书写一个模块。
- 开发环境下,不必显式写明模块的ID和模块的依赖。
2、为什么选用 CMD
#2.1、路径清晰
如上图,animation.js
模块依赖了see.js
模块,依赖关系一目了然,并且在 idea 编辑器里可以通过comman|ctrl
键单击该路径可以直达该模块,非常适合快速开发。
#2.2、提示清晰
在开发过程中,各种模块使用起来,难免会对部分模块的 API 不是很熟悉,这时候编辑器的智能提示就非常有用了。
参数提示:
#2.3、定位清晰
如上图,被依赖的模块路径书写错误,有非常明显的错误提示,可以非常快捷的定位。
因为 nodejs 的模块依赖就是这样的,所以只需要在编辑器配置里勾选 libraries 里的 node 相关选项即可:
3、加载策略
我们约定,每个页面都有且最多只有一个入口模块。模块加载器通过分析入口模块所依赖的模块,然后通过路径的相对关系,找到所依赖的模块。通过这一层层的递归查找过程,直到没有被依赖模块为止,整个寻找过程结束。查找结束之后,才开始从入口模块开始执行,依次递归调用到模块依赖链的终点,这个过程是一个嵌套的关系,因此形成的堆栈也非常的深,不过目前的浏览器都支持成千上万的嵌套层级,无需过分担心。看似原理比较简单,就是一个分析依赖,执行依赖的过程。
假设当前有一个动画模块animation.js
。
首先,需要判断需要加载的模块,即是入口模块,这需要手动指定。
然后,该模块加载完毕会执行define
方法,该方法有一个参数,参数类型为function
。
反观模块加载器的define
方法:
其次,通过分析它的源码:
得到被依赖的模块,注册到模块 MAP 里:
然后,重复上述过程。直到:
最后再执行入口模块即可。
4、构建过程
构建过程与加载策略是一致的,区别有2:
- 加载依赖之后,会将当前模块进行压缩,并写入缓存。
- 最后执行入口模块的步骤舍去。