comTg / comTg.github.io

0 stars 0 forks source link

commonJs, AMD, UMD, es6模块化的区别 #4

Open comTg opened 2 years ago

comTg commented 2 years ago

模块化概念

模块化就是把逻辑代码拆分成独立的块,各自封装,互相独立,每个块自行决定对外暴露什么,同时自行决定引入执行哪些外部代码。

commonJs

Node 应用由模块组成,采用 CommonJS 模块规范。也就是说CommonJs是应用在node服务器端的,如果浏览器想使用CommonJs规范的话需要用 browserify库 来进行转化。(后面会有例子) CommonJs分为两部分:moudle对象和requeire命令

  1. module对象 Node内部提供了一个Module构建函数, 所有模块都是Module实例
    function Module(id, parent) {
    this.id = id;
    this.exports = {};
    this.parent = parent;
    // ...
    }

    每个模块内部,都有一个module对象,代表当前模块。它有以下属性。

module.exports属性表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取module.exports变量。

//a.js
module.exports = {
  name: 'ysl',
  age: '27'
}
let obj = require('./a.js')
console.log(obj)  // { name: 'ysl', age: 27 }

除了使用module.exports的方式导出值之外,还可以使用export导出

//a.js
export.name = 'ysl'
export.age = 27
// 注意不能 export = {name:'ysl',age:27},这种方式是无效的

上面两种方式导出的结果是一致的

  1. require命令

上面我们已经将内容导出,现在是怎么把加载导出的内容,node内置的require命令用于加载模块文件

//a.js
module.exports = {name:'ysl',age:27}
//b.js
let obj = require(./a.js)
console.log(obj) // {name:'ysl',age:27}

需要注意点一:require第一次加载某个模块时,Node会缓存该模块。以后再加载该模块,就直接从缓存取出该模块的module.exports属性。 需要注意点二:CommonJS模块的加载机制是,输入的是被输出的值的拷贝。也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。

AMD

因为commonJs加载是同步加载的,在浏览器中如果某个模块加载时间很长,整个应用就会停在那里等,页面会出现卡死的现象 AMD采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,这个回调函数才会运行。 require.js类库实现了AMD规范,下面讲讲其基本用法:

1、下载require.js: npm install requirejs
2、引用require.js
<script src='../node_modules/requirejs/require.js' data-main='./index'></script>
// data-main属性的作用是,指定网页程序的主模块。在上例中,就是js目录下面的index.js,这个文件会第一个被require.js加载。由于require.js默认的文件后缀名是js,所以可以把index
3、编写index.js模块代码,主模块是依赖其他模块的入口,这时就要使用AMD规范定义的的require()函数加载依赖模块

 // index.js
 require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
    // some code here
       // 可以在这里编写模块加载后的代码
 });
 // require()函数接受两个参数:
 // 第一个参数是一个数组,表示所依赖的模块['moduleA', 'moduleB', 'moduleC']
 // 第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用
 // 注意['moduleA', 'moduleB', 'moduleC']这里面的三个模块与index.js在同一个目录
4、模块的写法,AMD提供define方法,调用define并传入一个函数

// moduleA.js
  define(function (){
    var add = function (x,y){
      return x+y;
    };
    return {
      add: add
    };
  });
// index.js
  require(['moduleA'], function (moduleA){
    console.log(moduleA)
       //moduleA就是moduleA.js模块传入的函数执行后返回的对象{add:function}
 });

以上就是符合AMD规范的require.js基本用法

UMD规范

Universal Module Definition - 前后端跨平台的模块化解决方案

实现原理:

ES6模块

ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。不再需要UMD模块格式了,将来服务器和浏览器都会支持 ES6 模块格式。 es6模块的语法分为两部分: export模块导出, import模块导入

CommonsJs与ES6之间的差别

comTg commented 2 years ago

node和浏览器分别加载es6与commonJs的方式

node加载es6模块的方式

1、 ES6 模块采用.mjs后缀文件名。 2、 项目的package.json文件中,指定type字段为module。(注意:如果没有type字段,或者type字段为commonjs,则.js脚本会被解释成 CommonJS 模块。) 总结为一句话:.mjs文件总是以 ES6 模块加载,.cjs文件总是以 CommonJS 模块加载,.js文件的加载取决于package.json里面type字段的设置。

node默认采用commonJs模块模块的方式

// a.js
module.exports = {name:'ysl}
// main.js
let obj = require('./a.js')
// node环境可以直接使用

浏览器加载es6模块方式

浏览器加载 ES6 模块,也使用 Githubissues.

  • Githubissues is a development platform for aggregating issues.