前端模块规范

101 阅读2分钟

Script标签

一般是同步加载,如果需要异步加载需要使用defer / async

defer:要等到整个页面在内存中正常渲染结束,才会执行;多个脚本时,按顺序执行

async:一旦下载完,渲染引擎就会中断渲染,执行这个脚本再继续渲染。多个脚本时,不能保证按执行顺序

AMD

  • 异步模式加载模块
  • 加载模块 require 接受两个参数,第一个是要引入的模块名数组,第二个是一个回调函数
  • 定义模块采用的是define,如果这个模块还依赖其他模块,那么define第一个参数必须是一个数组,指明模块的依赖关系
   // dataService.js

define(['math'], function (math) {
  function doSomething() {
    let result = math.add(2, 9);
    console.log(result);
  }
  return {
    doSomething
  };
});

特点: AMD允许输出的模块兼容CommonJS 异步并行加载,不阻塞 DOM 渲染。 推崇依赖前置,也就是提前执行(预执行),在模块使用之前就已经执行完毕。

CMD

  • CMD 是通用模块加载
  • 定义模块使用全局函数define,接收一个 factory 参数,可以是一个函数,也可以是一个对象或字符串;
  1. factory 是函数时有三个参数,function(require, exports, module):
    • require:函数用来获取其他模块提供的接口require(模块标识ID)
    • exports: 对象用来向外提供模块接口
    • module :对象,存储了与当前模块相关联的属性和方法
   // 定义 a.js 模块,同时可引入其他依赖模块,及导出本模块
   define(function(require, exports, module) {
   
     var $ = require('jquery.js')
    
     exports.price= 200;  
   });

AMD 与 CMD 的区别

  1. AMD 是提前执行,CMD 是延迟执行
  2. AMD 是依赖前置,CMD 是依赖就近
   // AMD 
   define(['./a', './b'], function(a, b) {  // 在定义模块时 就要声明其依赖的模块
       a.doSomething()
       // ....
       b.doSomething()
       // ....
   })
   
   // CMD
   define(function(require, exports, module) {
      var a = require('./a')
      a.doSomething()
      // ... 
      
      var b = require('./b') // 可以在用到某个模块时 再去require
      b.doSomething()
      // ... 
   })

CommonJS

  • 同步模式加载模块
  • 加载模块采用的是require
  • 定义/导出模块
exports.属性 = 值
exports.方法 = 函数

UMD(Universal Module Definition)

  • UMD是AMD和CommonJS的糅合
  • UMD的实现很简单:
    1. 先判断是否支持Node.js模块(exports是否存在),存在则使用Node.js模块模式。
    2. 再判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。
    3. 前两个都不存在,则将模块公开到全局(window或global)。

ES6模块化

ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。

treeshaking依赖了es6的模块化规范,才能实现的