JS模块化详解- 模块化规范

136 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

模块化规范分为四大类,分别为CommonJS、AMD、CMD、还有ES6的模块化

CommonJS

规范

说明

  • 每个文件都可当作一个模块。
  • 在服务器端: 模块的加载是运行时同步加载的。
  • 在浏览器端: 模块需要提前编译打包处理

基本语法

暴露模块

// example.js
var a = 5;
var addA = function (value) {
  return value + a;
};
module.exports.a = a;
module.exports.addA = addA;

var example = require('./example.js');//如果参数字符串以“./”开头,则表示加载的是一个位于相对路径
console.log(example.a); // 5
console.log(example.addA(1)); // 6

实现

1.在服务端实现CommonJS的有Node.js。 2.浏览器端实现的是Browserify,也称为CommonJS的浏览器端的打包工具。

两者的区别是:

  • Browserify是在转译(编译)时就会加载打包(合并)require的模块。
  • Node.js运行时动态加载模块(同步)

AMD

规范

说明

  • 专门用于浏览器端, 模块的加载是异步的。

基本语法

定义暴露模块

//定义没有依赖的模块
define(function(){
    return 模块
})
//定义有依赖的模块
define(['module1', 'module2'], function(m1, m2){
    return 模块
})
//入口js配置
require(['module1', 'module2'], function(m1, m2){
    使用m1/m2
})

引入使用模块

//页面引入使用
<script type="text/javascript" src="js/libs/require.js" data-main="js/main.js"></script>

实现(浏览器端)

Require.js。

CMD

规范

说明

  • Common Module Definition(通用模块定义)。
  • 专门用于浏览器端, 模块的加载是异步的。
  • 模块使用时才会加载执行。

基本语法

定义暴露模块

//定义没有依赖的模块
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
})

引入使用模块

//页面引入使用
<script type="text/javascript" src="js/libs/sea.js"></script>
<script type="text/javascript">
  seajs.use('./js/modules/main')
</script>

实现(浏览器端)

Sea.js

ES6模块化

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

规范

说明

  • 依赖模块需要编译打包处理

基本语法

暴露模块-export:

  1. 分别暴露:export 暴露内容
  2. 统一暴露:export {xxx, yyy}
  3. 默认暴露:export defalut 暴露内容

引入模块-import:

  1. import {xxx,yyy} from './module1'
  2. import module3 from './module3'

实现(浏览器端)

  • 使用Babel将ES6编译为ES5代码。
  • 使用Browserify编译打包js。

ES6 模块的运行机制与 CommonJS 不一样。ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块

总结

CommonJS规范主要用于服务端编程,加载模块是同步的,这并不适合在浏览器环境,因为同步意味着阻塞加载,浏览器资源是异步加载的,因此有了AMD CMD解决方案。

AMD规范在浏览器环境中异步加载模块,而且可以并行加载多个模块。不过,AMD规范开发成本高,代码的阅读和书写比较困难,模块定义方式的语义不顺畅。

CMD规范与AMD规范很相似,都用于浏览器编程,依赖就近,延迟执行,可以很容易在Node.js中运行。不过,依赖SPM 打包,模块的加载逻辑偏重

ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。