前端模块化commonJS,CMD,AMD,UMD,es6 module

随着前端业务越来越复杂,代码量也越来越多,因此模块化十分必要,因此,一些模块化工具标准出现。

1、Commonjs

用于nodejs环境,它使用 require 引用和加载模块,exports 定义和导出模块,module 标识模块。有人试图将其引入浏览器环境,由于node服务器环境上文件总是位于服务器上,加载速度较快,因此使用同步加载即可;但浏览器需要从服务端下载文件,所以说如果用CommonJS的require方式加载模块,需要等代码模块下载完毕,并运行之后才能得到所需要的API。如果我们在某个代码模块里使用CommonJS的方法require了一个模块,而这个模块需要通过http请求从服务器去取,如果网速很慢,而CommonJS又是同步的,所以将阻塞后面代码的执行,从而阻塞浏览器渲染页面,使得页面出现假死状态。因此产生了异步加载,主要是AMD和CMD

2、AMD

用于浏览器环境,依赖前置,提前执行。主要有requirejs,它主要有两个接口:define 和 require。define 是模块开发者关注的方法,而 require 则是模块使用者关注的方法。
优点:1、首先,尽早执行依赖可以尽早发现错误。  
2、尽早执行依赖通常可以带来更好的用户体验。
缺点:1、容易产生浪费。有些模块加载后未使用或者使用较晚
2、开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅;不符合通用的模块化思维方式,是一种妥协的实现。

define() 函数:
define(id?, dependencies?, factory);
//id :可选参数,它指的是模块的名字。
//dependencies:可选参数,定义中模块所依赖模块的数组。
//factory:模块初始化要执行的函数或对象
需要注意的是,dependencies有多少个元素,factory就有多少个传参,位置一一对应。使用栗子:

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {  
    exports.verb = function() {            
        return beta.verb();            
        //Or:
        //return require("beta").verb();        
    }    
});

3、CMD:

用于浏览器环境,依赖就近,延迟执行。主要实现为sea.js
CMD是SeaJS在推广过程中生产的对模块定义的规范,在Web浏览器端的模块加载器中,SeaJS与RequireJS并称,SeaJS作者为阿里的玉伯。CMD规范专门用于浏览器端,模块的加载是异步的,模块使用时才会加载执行。CMD规范整合了CommonJS和AMD规范的特点。在 Sea.js 中,所有 JavaScript 模块都遵循 CMD模块定义规范。
优点:依赖就近,延迟执行 可以很容易在 Node.js 中运行;
缺点:依赖 SPM 打包,模块的加载逻辑偏重

//定义没有依赖的模块
define(function(require, exports, module){
  exports.xxx = value
  module.exports = value
})

//定义有依赖的模块
define(function(require, exports, module){
  //引入依赖模块(同步)
  var module2 = require('./module2')
  //引入依赖模块(异步)
    require.async('./module3', function (m3) {
    })
  //暴露模块
  exports.xxx = value
})

4、UMD

nodejs和浏览器环境都支持,是common和AMD的统一,能够兼容他们,这样我们在开发时,就不需要再去考虑依赖模块所遵循的规范了,UMD的出现就是为了解决这个问题。(没有兼容CMD吧)

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD
        define(['jquery'], factory);
    } else if (typeof exports === 'object') {
        // Node, CommonJS之类的
        module.exports = factory(require('jquery'));
    } else {
        // 浏览器全局变量(root 即 window)
        root.returnExports = factory(root.jQuery);
    }
}(this, function ($) {
    //    方法
    function myFunc(){};
 
    //    暴露公共方法
    return myFunc;
}));

5、ES6 Module

设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及导入和导出的变量,也就是所谓的"编译时加载"。主要语法是import和export

6、对比

common引入的是一个拷贝,而es6module引入的是引用,可以实时变化,比如文件中有一个settimeout,延时后再调用可获得最新值,但是commonjs不能获取最新值。
commonjs或AMD,都是运行时加载,在编译阶段只判断语法层面对不对,如果引入了不存在的变量等只有在执行时才会发现。
ES6 可以因为是一边编译一边执行,在编译阶段会检查引入变量是否存在、引入模块是否存在等,问题更早暴露。

7、编译时和运行时知识点扩展

编译时
编译:将源代码翻译成机器能识别的语言(二进制)。计算机还是那个计算机,他至今还是只能看懂01,但随着时间的推移和人类的进步,逐渐出现了很多高级语言,高级语言之所以高级就在于我们可以用一种简单的方式比如if elese 来实现我们的代码逻辑,但最终在执行的时候计算机还是没办法识别的,这个时候就需要一个处理过程"编译",将大家平时写的if else 翻译成机器可以看懂的语言。那负责编译的这部分,我们一般称之为 编译器。

那编译时就会做一些简单的翻译工作,比如检查你有没有粗心写错啥关键字了啊。会进行词法分析,语法分析之类的。就像个老师检查学生的作文中有没有错别字和病句一样.如果发现啥错误编译器就告诉你。开始编译时,如果有errors或者warning信息,都是编译器检查出来的。所谓这时的错误就叫编译时错误,这个过程中做的类型检查也就叫编译时类型检查,或静态类型检查(所谓静态嘛就是没把真把代码放内存中运行起来,而只是把代码当作文本来扫描下)。

运行时
所谓运行时就是代码跑起来了。被装载到内存中去了。(你的代码保存在磁盘上没装入内存之前是个文件。只有跑到内存中才变成活的)。而运行时类型检查就与前面讲的编译时类型检查(或者静态类型检查)不一样。不是简单的扫描代码.而是在内存中做些操作,做些判断以确定我们的程序是否存在错误。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值