前端模块化CommomJs、AMD、CMD以及ES6的import详解

模块化

模块化是指将一个复杂的系统分解为多个模块,方便编码,同时下降代码复杂性,下降代码耦合度,方便部署,提升效率,避免了命名冲突,也能够减小变量空间污染,更好的分离代码,方便按需加载,更高的复用性,更高的可维护性。常见的模块化有CommonJs、AMD、CMD、ES6,下面就分别来介绍他们。html

CommonJs

CommonJs将每一个javaScript文件看成是一个模块, 其内部定义的变量函数等都属于这个模块,咱们能够向外部暴露咱们想要暴露的。可是CommonJs必须在node环境下才能使用,它是为node而生的,只有使用node环境才能运行,而浏览器是不支持CommonJs的,必须使用一些转换工具,将咱们服务器端的CommonJs语法转化为浏览器识别的语法。java

CommonJs中,每个javaScript文件都会隐士的被包裹在一个当即函数里面,例以下面的例子node

var name = 'xxx'
module.exports = {
    name: name
}

最终会被转换成下面这个样子api

(function(exports, require, module, __filename, __dirname){
    var name = 'xxx'
    module.export = {
        name: name
    }
})

exports、 require、 module、 __filename、 __dirname

exportsmodule.exports实际上是一个东西,只不过须要注意使用exports不能改变它的指向。
require是用来引入咱们须要的外部模块的,他是同步加载的,适用于服务器端。
__filename__dirname分别是当前执行的文件路径和文件夹路径。浏览器

使用CommonJs

通常咱们能够直接使用node 文件名直接将文件置于node环境运行,这样是彻底ok的。可是假若咱们须要将它放到浏览器端运行,也就是引入到html文件中,因为浏览器是不认识前面咱们说的exports、require...这些语法的,因此咱们能够借助像Browserify这样的转换工具。咱们看下面的例子服务器

// m1.js
module.exports = {
  name: 'xxx'
}

// m2.js
module.exports = {
  age: '100'
}

// main.js
const name = require('m1')
const age = require('m2')
console.log(name, age)

// index.html
...
<script src="./node_modules/main.js"></script>  
...

当咱们打开html的时候浏览器是会报错的,以下babel

Uncaught ReferenceError: require is not defined
    at main.js:1

咱们能够借助Browserify,将Browserify下载下来,将咱们的main.js使用它转换后,将转换后的文件引入页面中,修改后咱们就能正常运行了,修改后的html代码以下网络

<script src="./node_modules/bundle.js"></script>

browerify用法很简单,能够看它的文档异步

AMD

CommonJs为服务器端而生,采用的同步加载方式。所以不适用浏览器。由于浏览器须要到服务器加载文件,请求时间远大于本机读取的时间,假若文件较多,网络迟缓就会致使页面瘫痪,因此浏览器更但愿可以时间异步加载的方式。
AMD规范则是异步加载模块,容许指定回调函数。等模块异步加载完成后便可调用回调函数。它依赖一个库require.js,这里就简单的说一下它的用法,具体请参考文档。
AMD的核心思想就是经过define来定义一个模块,而后使用require来加载一个模块。
``async

define基本使用

define(moduleId,['module1','mdule2'],function(m1,m
       
2){...});

moduleId为当前定义的模块ID,若是不写默认是当前文件名,
module1等是咱们要引入的模块的IDfunc的参数就是导入的模块例如m1就是module1导入的变量,以后咱们使用m1就行,须要注意的是若是咱们要像module.exports同样向外暴露变量等,咱们须要在每一个模块的func中返回咱们须要暴露的东西

require

在咱们须要定义模块的地方使用define,当咱们须要使用这些暴露的模块的时候,使用require(['module1','module2'],function(m1, m2) {...})func中写咱们的代码
同时须要在最上面配置一下咱们须要引入的模块的路径以及它涉及到的模块的路径使用require.config({paths: { 模块一: 路径,模块二: 路径}})
下面给一个简单的AMD例子

// m1.js
define(function() {
  return {
    name: 'xxx'
  }  
});
// m2.js
define(function() {
  return {
    age: '100'
  }  
});
// main.js
require.config({
  path: {
    m1: './m1.js',
    m2: './m2.js'
  }
})
require(['m1', 'm2'], function (m1, m2) {
  console.log(m1.name, m2.age)
})
// index.html
...
<script src="./node_modules/require.js" data-main="./node_modules/main.js"></script>  
...

CMD

CMD异步加载,跟AMD的主要区别在于,AMD依赖前置,提早加载依赖。而CMD就近加载,按需加载。

产物seaJs,跟requireJs使用有些类似。
若是咱们想使用SeaJS,咱们只须要将其引入到咱们的页面中,而后使用seajs.use('入口文件'),咱们就能够在咱们的入口文件中使用咱们的CMD
CMD的核心思想就是经过define来定义一个模块,而后使用require来加载一个模块,听起来和AMD有点相似,可是实际的使用仍是有区别的。

define

当咱们在一个文件中定义一个模块的时候,能够像下面这样

define(function(require,exports,module){
    module.exports = {}
})

require

requireCMD中分为同步和异步下面分别给出同步和异步使用的方式

// 同步
var module = require('xxx')
//异步
var module = require.async('m1', function(m1){
...
})

ES6

ES6自带模块化,可使用 import 关键字引入模块,经过 export 关键字导出模块,功能较之于前几个方案更为强大,也是咱们所推崇的,可是因为ES6目前没法在浏览器中执行,因此,咱们只能经过babel将不被支持的import编译为当前受到普遍支持的 require

相关文章
相关标签/搜索