Bootstrap

浅谈前端模块化

前端模块化,相信这个词对于做前端的同学来说,绝对不陌生,你对前端模块化的了解有多少呢?在这里我们就来聊聊前端模块化。

一.前端为什么要模块化?

javascript这门语言被创造出来时,它只是基于浏览器的。但自1996年以来,已经有各种各样的JavaScript平台可以在浏览器之外进行编程,官方定义的API只能构建基于浏览器的应用程序。人们逐渐认识到了问题的严重性:

  • JavaScript没有模块系统。要编写JavaScript脚本,必须以HTML格式管理,连接,注入或手动获取和评估它们。没有用于范围隔离或依赖关系管理的本机工具。
  • JavaScript没有标准库。它有浏览器API,日期和数学,但没有文件系统API,更不用说IO流API或二进制数据的原始类型。
  • JavaScript没有Web服务器或数据库之类的标准接口。
  • JavaScript没有管理依赖关系并自动安装它们的软件包管理系统,除了JSAN(不要与JSON混淆),这不符合范围隔离。

二.CommonJS,AMD,CMD与ES6模块化

      这其中我们需要重点掌握的是ES6和CommonJS,AMD与CMD只需了解,现在我们实际开发中已经基本不会用到了。

1.CommonJS

2009年,CommonJS出现了,CommonJS 通过定义处理许多常见应用程序需求的API来填补这一空白,最终提供与Python,Ruby和Java一样丰富的标准库。目的是应用程序开发人员能够使用CommonJS API编写应用程序,然后跨不同的JavaScript解释器和主机环境运行该应用程序。同时,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程,node.js是对commonJS规范的实现,这标志"Javascript模块化编程"正式诞生。在现在的前端开发中我们经常会用到node,node中的模块化就需要使用commonjs,所以掌握commonjs是必须的。

通过module.exports导出模块

var x = 5;
var addX = function (value) {
  return value + x;
};
module.exports.x = x;
module.exports.addX = addX;

//同时导出多个
module.exports = {
  x,
  addX
}

 通过require导入模块

var example = require('./example.js');

console.log(example.x); // 5
console.log(example.addX(1)); // 6

关于nodejs和commonjs在阮一峰老师的这篇文章中有详细描述http://javascript.ruanyifeng.com/nodejs/module.html

2、ES6模块化

ES6推出了自己的模块化规范,使用export和import来进行导出和导入。

var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {firstName, lastName, year};
import {firstName, lastName, year} from './profile.js';

 

ES6 模块与 CommonJS 模块的差异

讨论 Node 加载 ES6 模块之前,必须了解 ES6 模块与 CommonJS 模块完全不同。

它们有两个重大差异。

  • CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。

第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

具体可参考阮一峰老师的ES6 http://es6.ruanyifeng.com/#docs/module

3.AMD

AMD就只有一个接口:define(id?,dependencies?,factory);

它要在声明模块的时候制定所有的依赖(dep),并且还要当做形参传到factory中,像这样:

 define(['dep1','dep2'],function(dep1,dep2){...});

要是没什么依赖,就定义简单的模块,下面这样就可以啦

 define(function(){
     var exports = {};
     exports.method = function(){...};
     return exports;
 });

这里有define,把东西包装起来,那Node实现中怎么没看到有define关键字呢,它也要把东西包装起来呀,其实吧,只是Node隐式包装了而已.....

这有AMD的WIKI中文版,讲了很多蛮详细的东西,用到的时候可以查看:AMD的WIKI中文版

4、CMD

大名远扬的玉伯写了seajs,就是遵循他提出的CMD规范,与AMD蛮相近的,不过用起来感觉更加方便些,最重要的是中文版,应有尽有:seajs官方doc

1 define(function(require,exports,module){...});

用过seajs吧,这个不陌生吧,对吧。

前面说AMD,说RequireJS实现了AMD,CMD看起来与AMD好像呀,那RequireJS与SeaJS像不像呢?

虽然CMD与AMD蛮像的,但区别还是挺明显的,官方非官方都有阐述和理解,我觉得吧,说的都挺好:

官方阐述SeaJS与RequireJS异同

SeaJS与RequireJS的最大异同(这个说的也挺好)

 

 

 

;