美文网首页
CommonJS,AMD,CMD,ES6 Module

CommonJS,AMD,CMD,ES6 Module

作者: _咻咻咻咻咻 | 来源:发表于2021-01-29 17:25 被阅读0次

    他们都是用于在模块化定义中使用的,AMD、CMD、CommonJs是ES5中提供的模块化编程的方案,import/export是ES6中定义新增的。

    一、CommonJS

    服务端模块规范,Node.js采用了这个规范。
    一个单独文件就是一个模块,通过require方法来同步加载要依赖的模块,然后通过exports或则module.exports来导出需要暴露的接口。

    require("module");
    require("../file.js");
    exports.doStuff = function() {};
    module.exports = someValue;
    

    加载模块是同步的,只有加载完成后才能执行后面的操作,也就是当要用到该模块了,现加载现用,不仅加载速度慢,而且还会导致性能、可用性、调试和跨域访问等问题。Node.js主要用于服务器编程,加载的模块文件一般都存在本地硬盘,加载起来比较快,不用考虑异步加载的方式,因此,CommonJS规范比较适用。然而,这并不适合在浏览器环境,同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。

    二、AMD

    异步模块定义,AMD推崇依赖前置(在定义模块的时候就要声明其依赖的模块)。
    它要在声明模块的时候指定所有的依赖 dependencies ,并且还要当做形参传到factory 中,对于依赖的模块提前执行,依赖前置。
    核心接口是:define(id?, dependencies?, factory) 。

    • id:可选参数,用来定义模块的标识,如果没有提供该参数,脚本文件名(去掉拓展名)
    • dependencies:是一个当前模块依赖的模块名称数组
    • factory:工厂方法,模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。

    实现RequireJS; curl;

    // 定义模块 myModule.js
    define(['dependency'], function(){
        var name = 'Byron';
        function printName(){
            console.log(name);
        }
        return {
            printName: printName
        };
    });
    
    // 加载模块
    require(['myModule'], function (my){
      my.printName();
    });
    

    优点:适合在浏览器环境中异步加载模块。可以并行加载多个模块。
    缺点:提高了开发成本,并且不能按需加载,而是必须提前加载所有的依赖。

    三、CMD - 同步模块定义

    同步模块定义,CMD推崇依赖就近(只有在用到某个模块的时候再去require——按需加载)。
    实现Sea.js ;coolie

    // 定义模块  myModule.js
    define(function(require, exports, module) {
      var $ = require('jquery.js')
      $('div').addClass('active');
    });
    
    // 加载模块
    seajs.use(['myModule.js'], function(my){
    
    });
    

    优点:依赖就近,延迟执行 可以很容易在 Node.js 中运行;
    缺点:依赖 SPM 打包,模块的加载逻辑偏重;

    AMD和CMD区别:
    AMD在加载完成定义(define)好的模块就会立即执行,所有执行完成后,遇到require才会执行主逻辑。(提前加载)
    CMD在加载完成定义(define)好的模块,仅仅是下载不执行,在遇到require才会执行对应的模块。(按需加载)
    AMD用户体验好,因为没有延迟,CMD性能好,因为只有用户需要的时候才执行。

    四、ES6 Module

    ES6自带模块化,可以使用import关键字引入模块,通过export关键字到处模块,功能较之前几个方案更为强大,但是由于ES6目前无法在浏览器中执行,所以,需要通过babel将不支持的import编译为当前收到广泛支持的require。

    ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。

    CommonJS vs ES6 Module:

    • CommonJS支持动态导入,也就是 require(${path}/xx.js),ES6目前不支持
    • CommonJS是同步导入,因为用于服务端,文件都在本地,同步导入即使卡住主线程影响也不大。而ES6是异步导入,因为用于浏览器,需要下载文件,如果也采用同步导入会对渲染有很大影响。
    • ES6模块中的值属于【动态只读引用】。只读:import的变量是只读的,不论是基本数据类型还是复杂数据类型,在不能在导入的文件修改,复杂数据类型可以修改属性值不会报错,但是不建议这么做。动态:原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
      CommonJS导出时都是值拷贝,就算导出的值变了,导入的值也不会改变,当导出的是复杂数据类型时,属于浅拷贝,由于引用相同,所以修改会互相影响。使用require命令加载某个模块时,就会运行整个模块的代码。当再次使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值,除非手动清除系统缓存。
    • ES6编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,在运行时才能确定。

    相关文章

      网友评论

          本文标题:CommonJS,AMD,CMD,ES6 Module

          本文链接:https://www.haomeiwen.com/subject/mloqtltx.html