JS模块化专题二
NodeJS 模块化体验
NodeJS诞生带来前所未有的模块化体验,不在需要html导入JS,真正实现JS模块之间的相互独立与依赖。
require('......'); // 引入模块
module.exports // 导出模块
CommonJS 实现
module_a.js
var a = (function () {
return [1, 2, 3, 4, 5].reverse();
})();
module.exports = {
a
}
module_b.js
var moduleA = require('./module_a') ;
var b = (function () {
return moduleA.a.concat([6, 7, 8, 9, 10]);
})();
module.exports = {
b
}
module_c.js
import moduleB = require('./moduleB');
var c = (function () {
return moduleB.b.join('-');
})();
module.exports = {
c
}
index.js
import moduleA require('./moduleA');
import moduleB require('./moduleB');
import moduleC require('./moduleC');
console.log(moduleA.a);
console.log(moduleB.b);
console.log(moduleC.c);
关于CommonJS
CommonJS是一种模块化规范,不是JS方法集合、JS库等;
CommonJS规范来源于NodeJS;
CommonJS使用的方法,实际是同步方法,文件加载是同步进行的;
CommonJS使用require关键字,只要引用,就会创建一个模块实例(实例化);
CommonJS存在缓存机制,只要require导入,模块就会被缓存,不会多次进行导入;
CommonJS是在Node环境中运行的,客户端环境无法运行;
require在引用后实质是一个立即执行函数。
;(function (exports, require, module, __filename, _dirname) {
})();
AMD
客户端的”CommonJS” - AMD,但两者只是表面上相似;
CommonJS是同步模块定义,AMD是异步模块定义(Asynchronous Module Definition);
RequireJS是AMD规范的实现,AMD规范是由RequireJS实现的,可以实现异步加载模块;
AMD不支持浏览器,不需要运行在node环境,也不需要运行在webpack中;
define(moduleName, [module], factory); // 定义模块
require([module], callback); // 引入模块
AMD是所有模块加载完毕,才会执行回调函数,是前置依赖,即依赖前面的模块;
不会考虑模块的加载顺序问题,解决模块加载顺序问题;
规范了模块的输入与输出,实际是用async的方式异步加载模块;
RequireJS
module_a.js
define('moduleA', function () {
var a = [1, 2, 3, 4, 5];
return {
a: a.reverse()
}
});
module_b.js
define('moduleB', ['moduleA'], function (moduleA) {
var b = [6, 7, 8, 9, 10];
return {
b: moduleA.a.concat(b)
}
});
module_c.js
define('moduleC', ['moduleB'], function (moduleB) {
return {
c: moduleB.b.join('-')
}
});
index.js
// 配置路径
require.config({
paths: {
moduleA: 'js/module_a',
moduleB: 'js/module_b',
moduleC: 'js/module_c'
}
})
// 所有模块加载完毕,才会执行回调函数
require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC) {
console.log(moduleA.a);
console.log(moduleB.b);
console.log(moduleC.c);
});
index.html
<script type="text/javascript" src="js/require.js" />
<script type="text/javascript" src="js/index.js" />
CMD
阿里也为模块化做了贡献-CMD
通用模块定义(Common Module Definition)
浏览器同样不支持CMD规范,使用SeaJS框架实现
define(function (require, exports, module) {}); // 定义模块
seajs.use([module路径], function (moduleA, moduleB, moduleC) {}); // 使用模块
CMD require 引入模块、define 定义模块
exports 导出模块、module 操作模块
使用模块时,需要配置模块URL;
依赖加载完毕后执行factory;
CMD是依赖就近,按需加载模块,与CommonJS、AMD有本质区别;
AMD是依赖前置,CMD是需要的时候去加载模块;
SeaJS
module_a.js
define(function (require, exports, module) {
var a = [1, 2, 3, 4, 5];
return {
a: a.reverse()
}
});
module_b.js
define(function (require, exports, module) {
var moduleA = require('module_a'),
b = [6, 7, 8, 9, 10];
return {
b: moduleA.a.concat(b)
}
});
module_c.js
define(funvtion (require, exports, module) {
var moduleB = require('module_b');
return {
c: moduleB.b.join('-')
}
});
index.js
seajs.use(['module_a.js', 'module_b.js', 'module_c.js'], function (moduleA, moduleB, moduleC) {
console.log(moduleA.a);
console.log(moduleB.b);
console.log(moduleC.c);
});
index.html
<script type="text/javascript" src="js/sea.js" />
<script type="text/javascript" src="js/index.js" />
ES6 模块化
ES6官方终于给出权威答案 - ES6模块化
import module from '模块路径'; // 导入模块
export module; // 导出模块
module_a.js
export default {
a: [1, 2, 3, 4, 5].reverse()
}
module_b.js
import moduleA from './module_a';
export default {
b: moduleA.a.concat([6, 7, 8, 9, 10])
}
module_c.js
import moduleB from './module_b';
export default {
c: moduleB.b.join('-')
}
index.js
import moduleA from './module_a';
import moduleB from './module_b';
import moduleC from './module_c';
console.log(moduleA.a);
console.log(moduleB.b);
console.log(moduleC.c);
commonJS 与 ES6
export.js
exports.a = 0;
setTimeout(() => {
console.log('来自export', ++exports.a); // 1
}, 300);
common.js
const { a } = require('./export');
setTimeout(() => {
console.log('来自commonjs', a); // 0
}, 500);
es6.js
import { a } from './export';
setTimeout(() => {
console.log('来自ES6', a); // 1
}, 500);
ES6与CommonJS区别
- commonjs 模块输出的是一个值的拷贝;
es6 模块输出的是值的引用; - commonjs 模块是在运行时加载;
es6 模块是在编译时加载;