javascript模块化

模块化的意义:html

  • 组件的复用,下降开发成本和维护成本
  • 组件单独开发,方便分工合做
  • 模块化遵循标准,方便自动化依赖管理,代码优化,部署

1.模块化标准

ES6以前,JavaScript并无原生的模块机制,好在JavaScript很是灵活,有不少种写法能够将代码自然隔离,起到模块化的功能:前端

 //define var modules = {} modules.mod1 = { foo : function(){...}, bar : function(){...} ... } //call modules.mod1.foo()

在客户端这种方式基本是够用的,然而问题依然存在:你没法管理依赖,全部的代码都必须load到内存中,须要哪些模块必须由人工处理。分模块是工程化的产物,也是天然发展的结果,天然有不少尝试。很显然,模块之间互相依赖须要编写模块的时候遵循必定的规范。现存的规范还真很多,不知道ES6 可否终结这场混战:es6

  • AMD
  • CMD
  • closure
  • CommonJS
  • ES6

AMD和CMD分别是requireJS和seaJS定义的标准。使用纯原生的ES5语法意味者其只能使用闭包,书写和阅读都很怪异。值得一提的是AngularJS也使用相似的方式,以致于Angular的做者们都受不了,决定在AngularJS 2 使用新的语言AtScript,前端轮子太多,又造了一个,好在这个轮子造的比较好,兼容ES6 TypeScript规范,扯的远了,看看AMD长得啥样:web

AMD:gulp

 define(['./a', './b'], function(a, b) { ... })

Closure是google出品的前端工具,Closure提供了一系列工具和库,谷歌本身的多个项目都是使用Closure开发的。closure compiler经过模块间依赖的声明把全部被依赖的文件打包到一块儿,并且Closure的一大优点是若是采用破坏性压缩(ADVANCED)压缩率极高。浏览器

 //文件A goog.provide('module1') com.foo.bar = { ... } .... //文件B goog.require('module1') var a = com.foo.bar;

然而Closure并不完美,不一样的文件共享同一个全局对象,因此你不得不这样写 a.b.c=…。服务器

CommonJS是Node.js使用的模块化标准。Node.js对于前端开发者来讲不只仅能够提供一个Server,仍是一个完美的开发平台,在Node上使用Grunt/gulp构建web项目是件很爽的事情。Node的模块化声明的方式与Closure相似,只是更进一步,自然隔离了命名空间。上面的代码若是使用CommonJS的模块化规范能够这么写:闭包

 //文件A module.exports = {...} .... //文件B var a = require('./foo/bar')

browserify让使用CommonJS模块化规范的代码能够运行在客户端上。异步

 

2.静态加载与动态加载

在看ES6以前咱们先看模块加载的两种方式:ide

  • 静态加载:在编译阶段进行,把全部须要的依赖打包到一个文件中
  • 动态加载:在运行时加载依赖

AMD标准是动态加载的表明,而CommonJS是静态加载的表明。AMD的目的是用在浏览器上,因此是异步加载的。而NodeJS是运行在服务器上的,同步加载的方式显然更容易被人接收,因此使用了CommonJS。一样的道理,若是静态加载,那就使用同步的加载方式,若是动态加载就必须用异步的加载方式。

那么ES6采用何种加载机制?

ES6既但愿用简单的声明方式来完成静态加载,又不肯放弃动态加载的特性,而这两种方式几乎不可能简单的同时实现,因此ES6提供了两种独立的模块加载方法。

2.1 声明的方式

 import {foo} from module1 

2.2 经过System.import API的方式

 System.import('some_module') .then(some_module => { // Use some_module }) .catch(error => { ... });

再看下export的语法,与CommonJS很像,只不过没有了module这个对象,而直接调用export。 能够export任何一个 函数,变量,对象

 //expt.js export function abc(){}//export 一个命名的function  export default function(){} //export default function  export num=123 //export 一个数值  export obj={} export { obj as default }; //import import expt from 'expt'//default export  import {default as myModule} from 'expt' //rename  import {abc,num,obj} from 'expt'

更多细节能够看这篇文章:http://www.2ality.com/2014/09/es6-modules-final.html

目前来看,使用预编译的方式显然要好于使用动态加载,浏览器对ES6语法支持还不好,若是使用动态加载ES6,在浏览器端要作ES6到ES5的翻译工做,这个显然是重复低效的。可是随着浏览器对ES6支持加强,尤为是浏览器实现了动态加载API后,动态加载的优点就会展示:

  • 更流畅的用户体验,动态加载能够实现相似lazyload的加载方式,将download的时间分散
  • 更简洁的项目,无需预编译,项目能够少配置不少工具
  • HTTP/2的普及更倾向于使用多个小的请求,适合动态加载
相关文章
相关标签/搜索