「这是我参与2022首次更文挑战的第24天,活动详情查看:2022首次更文挑战」
1、设计思想
模块模式的设计思想:将逻辑分块各自封装,相互独立。有很多个模块时候,我们会给每个模块定义一个模块标识,然后通过标识符去定位匹配具体文件入口。在 Nodejs 中,模块标识符可能指向文件,也可能指向含有 index.js 文件的目录。模块封装也可能会使用其他的模块,就是依赖其他模块。
2、模块加载
那么在模块加载的时候如何加载?
Javascript 是顺序执行,且是单线程,当一个模块中依赖其他模块的时候,就会根据所依赖的顺序进行加载,只有所有的依赖都加载完成后,模块才会被加载。这样自然会产生很多问题,如加载时依赖包出现问题时就会导致阻塞,如因依赖导致性能问题等等。
依赖其中的模块时,是否可以实现按需加载呢?
JavaScript支持异步执行,所以也是可以支持按需加载,让 JavaScript 通知模块系统在必要时加载新模块,并在模块加载完成后提供回调。那么同样也是支持动态加载所依赖的模块。开发人员在程序结构中动态添加依赖。动态依赖必需都加载完才能执行模块,按需加载是在执行模块时有需要再加载。
3、ES6之前的模块加载器
3.1、CommonJS
CommonJS规范概述了同步声明依赖的模块定义。Nodejs的模块系统中使用了 CommonJS规范(实际使用了改版后的CommonJs,因 Node 主要在服务器环境下使用,所以无需考虑网络延迟)
var moduleA = require("moduleA");
module.exports = {
func_t
}
function func_t(){
var dd = moduleA.sprintf()
}
CommonJS 模块定义需要使用 require()指定依赖。模块永远是单例的,所以无论使用require引用多少次,都只会被加载一次。第一次被加载后就会缓存。
3.2、异步模块
异步模块定义 AMD,其模块定义系统会以浏览器为目标执行环境,运行在浏览器中的模块系统会按需获取依赖,并在依赖加载完成后立即执行依赖它们的模块。
AMD模块实现的核心是用函数包装模块定义。包装模块的函数是全局 define 的参数,它是由 AMD 加载器库的实现定义的。
define('moduleA',['moduleB','moduleC'], function(moduleB, moduleC){
// TODO Something
})
以上是 moduleA的模块定义,其依赖 moduleB ,moduleC,这两个模块将会异步加载。
3.3、通用模块 UMD
UMD主要是为了统一 CommonJS 和 AMD 生态系统。UMD模式创建的模块会在启动时检测使用何种生态然后进行适配。
(function(root,facory){
if(typeof define === 'function' && define.amd) {
define(['moduleA'],factory);
}else{
module.exports = factory(require('moduleA'))
}
})