模块化的问题从一开始就不存在。WWW刚出来的时候,html、JavaScript、CSS(JS和CSS都是后来在Netscape中引入浏览器的)都非常简单,不需要模块。改变。对模块化的要求是规模的产物。当网页演变成Web应用,浏览器端处理的逻辑越来越复杂,显示的样式和动画也越来越多,因此对工程化的要求也越来越高。因此出现了对模块化的需求。模块化的意义:组件复用,降低开发和维护成本组件单独开发,便于分工合作。模块化遵循标准并促进自动化依赖管理、代码优化和部署。长期以来,JavaScript一直被认为是一种简单的脚本语言。事实上,情况早就发生了变化,在最新版本中,JavaScript不再是脚本语言,而是一种通用的编程语言。脚本语言,比如shell,不是用来完成复杂的功能,而是用来做一些自动控制的,不需要模块化。用于构建复杂系统的通用编程语言(如Java)一般都有模块实现。1.在模块化标准ES6之前,JavaScript没有原生的模块机制。幸运的是,JavaScript非常灵活。代码的写法有很多种,自然隔离代码,起到模块化的作用://definevarmodules={}modules.mod1={foo:function(){...},bar:function(){...}...}//欢迎加入前端全栈开发交流圈一起学习交流:1007317281//callmodules.mod1.foo()这种方式在客户端基本够用了,但是问题遗留:不能管理依赖,所有代码都必须加载到内存中,需要哪些模块必须手动处理。子模块是工程的产物,也是自然发展的结果。自然有很多尝试。显然,模块之间的相互依赖性需要在编写模块时遵循一定的规范。有相当多的现有规范。不知道ES6能不能结束这场混战:AMDCMDclosureCommonJSES6AMD和CMD分别是requireJS和seaJS定义的标准。使用纯原生ES5语法意味着它只能使用闭包,写起来和读起来都很奇怪。值得一提的是AngularJS也使用了类似的方法,让Angular的作者们看不下去。他们决定在AngularJS2中使用新语言AtScript,前端轮子太多了,另造一个。幸运的是,这个轮子更好。兼容ES6TypeScript规范,差远了,看看AMD长啥样:AMD:define(['./a','./b'],function(a,b){...})ClosureisGoogle出品的前端工具,Closure提供了一系列的工具和库,Google自己的很多项目都是使用Closure开发的。Closure编译器通过模块间的依赖声明将所有依赖文件打包在一起,Closure的一大优势是如果使用破坏性压缩(ADVANCED)压缩率极高。//FileAgoog.provide('module1')com.foo.bar={...}//欢迎加入前端全栈开发交流圈一起学习交流:1007317281//FileBgoog.require('module1')vara=com.foo.bar;然而Closure并不完美,不同的文件共享同一个全局对象,所以你必须写a.b.c=...。CommonJS是Node.js使用的模块化标准。Node.js不仅可以为前端开发者提供一个服务器,更是一个完善的开发平台。使用Grunt/gulp在Node.js上构建Web项目非常酷。Node的模块化声明方式与Closure类似,但更进一步,自然地隔离了命名空间。上面的代码如果使用了CommonJS模块化规范,可以这样写//fileAmodule.exports={...}//filebvara=require('./foo/bar')browserify允许代码使用CommonJS模块化规范可以在客户端上运行。2.静态加载和动态加载在看ES6之前,我们先了解一下模块加载的两种方式:静态加载:在编译阶段,将所有需要的依赖打包到一个文件中动态加载:运行时加载依赖于AMD标准是Dynamically加载代表,而CommonJS是静态加载代表。AMD的目的是在浏览器上使用,所以是异步加载的。但是NodeJS运行在服务端,同步加载的方式显然更容易被人们接受,所以使用了CommonJS。同理,如果是静态加载,则使用同步加载方式,如果是动态加载,则必须使用异步加载方式。那么ES6使用的是什么加载机制呢?ES6希望用简单的声明方式完成静态加载,又不愿意放弃动态加载的特性,同时实现这两种方式几乎是不可能的,所以ES6提供了两种独立的模块加载方式。2.1import{foo}frommodule12.2声明方式通过System.importAPISystem.import('some_module').then(some_module=>{//Usesome_module}).catch(error=>{...});//欢迎加入前端全栈开发交流圈一起学习交流:1007317281看看export的语法,和CommonJS很像,只是没有module对象,直接调用export.你可以导出任何函数、变量、对象//expt.jsexportfunctionabc(){}//导出一个命名函数exportdefaultfunction(){}//导出默认函数exportnum=123//导出一个值exportobj={}export{objasdefault};//importimportexptfrom'expt'//defaultexportimport{defaultasmyModule}from'expt'//renameimport{abc,num,obj}from'expt'现在,使用预编译显然比使用动态加载要好。浏览器对ES6语法的支持仍然很差。如果使用ES6的动态加载,需要在浏览器端将ES6转为ES5,显然是重复且低效的。但是随着浏览器支持ES6,尤其是浏览器实现了动态加载API之后,动态加载的优势就会显现出来:更流畅的用户体验,动态加载可以实现类似lazyload的加载方式,分散下载时间,更简洁项目,无需预编译,项目可以配置很多工具。HTTP/2的流行倾向于使用多个小请求,适合动态加载。3.实践如果你现在使用ES6,你可以选择动态加载模块system.js或者Browserify的预编译方式。使用system.js+babel动态加载依赖。system.js是ES6动态模块加载的实现。我写了一个小DEMO:项目初始化bowerinstallbabelsystem.js--saveindex.htmlmain.jsexportdefault{sayHello:function(){console.log('hello')}}使用gulp+browserify+babel预编译。gulp是Node.js平台上的一个任务管理平台。预编译需要大量配置,非常繁琐。推荐使用yeoman生成项目骨架。例如,使用generator-es6-webapp。生成很简单,直接在项目目录下执行yoes6-webappmissingdependencies安装依赖即可。4.其他,ES6模块化对前端趋势意味着什么?有了更强大的前端,Web技术整体向前发展。HTML5的发展和一些优秀浏览器的支持推动了整个网络技术的向前发展。以前渲染等工作都是在后端做的,因为浏览器弱,还有IE老玩家拖着腿捣乱。简化编程模型,不需要手动管理JS依赖,不需要打包多个JS,有了WebComponents标准,Web的开发将不再依赖模板引擎和预编译引擎。前端也有深远的影响——以前浏览器是工具,现在浏览器是重要的工具,未来浏览器将是用户唯一的操作系统。感谢大家观看,如有不足,欢迎批评指正。获取信息???这次给大家推荐一个免费学习群,里面总结了移动应用网站开发,css,html,webpack,vuenodeangular,面试资源。欢迎对web开发技术感兴趣的同学加入Q群:???1007317281???,不管你是小白还是大牛,我都欢迎你,还有整理了一套高效的学习路线和教程大牛分享给大家免费分享,每天更新视频信息。最后祝大家早日学业有成,拿到满意的offer,快速升职加薪,走上人生巅峰。
