模块化的优势不言而喻:
相对于其他静态语言,JS最大缺陷就是天生不具有模块化,没有语言层面的命名空间的概念。问题如下:
jquery
时,必须先导入jquery
:<script src='jquery.js'></script>
<script src='jquery.plugin.js'></script>
一直以来,前端工程师们都在探索如何做到JavaScript模块化,其中以CommonJS,AMD,CMD为代表。
直到ES6 Module的出现,才从语言层面上解决了JS模块化的问题。
CommonJS是针对服务器或桌面应用环境下的JavaScript开发(非浏览器),其被Node.js采用为默认的模块化规范,并随着Node.js的流行被广大Web开发者熟知。
CommonJS有两个弊端,使其不适合浏览器环境开发:
使用方法如下:
exports
require
// foobar.js
//私有变量
var test = 123;
//公有方法
function foobar () {
this.foo = function () {
// do someing ...
}
this.bar = function () {
//do someing ...
}
}
//exports对象上的方法和变量是公有的var foobar = new foobar();
exports.foobar = foobar;
// main.js
//require方法默认读取js文件,所以可以省略js后缀
var test = require('./foobar').foobar;
test.bar();
在CommonJS基础上,还扩展了以下功能:
AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义";CMD是SeaJS 在推广过程中对模块定义的规范化产出。使用方式如下:
//AMD
define(['./a','./b'], function (a, b) {
//依赖一开始就写好
a.test();
b.test();
});
//CMD
define(function (requie, exports, module) {
//依赖可以就近书写
var a = require('./a');
a.test();
...
//软依赖
if (status) {
var b = requie('./b');
b.test();
}
});
上面的例子可以看出两者的区别:
ES6 Module是语言层面的规范,与应用场景无关,完全可以取代现有的 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。 目前受限与浏览器的实现程度,针对浏览器的模块化仍然需要构建工具进行编译。
ES6 Module与CommonJS类似,是一种静态模块规范,不支持异步加载。不过,结合其他框架或者构建工具(比如React的lazy load
,webpack的require.ensure
)可以实现按需加载和异步加载。
// react lazy loader
const Home = React.lazy(() => import('./pages/Home'));
const Page1 = React.lazy(() => import('./pages/Page1'));
const Page2 = React.lazy(() => import('./pages/Page2'));
// webpack
window.onload =require.ensure([], require => {
const b = require('./module.a.js');
b()
}, 'async')