浅谈前端模块化

  • 模块化编程
  • CommonJS
  • AMD(Asynchronous Module Definition)规范
  • requireJS与seaJS
  • requireJs 以及 seaJs 的区别

模块化编程:

@为了更好的开展话题,首先需了解什么是前端模块化

模块的由来:

其实模块化的诞生不难理解,我们知道因为随着网站逐渐的发展,嵌入网页的Javascript代码越来越庞大,而网页越来越像桌面程序,需要一个团队去分工协作,进行管理和测试等等,为了更好的管理网页的业务逻辑,产生了模块化编程的理念。

模块的定义:

模块就是实现特定功能的相互独立的一组方法。

模块的意义:

因为有了模块,我们能更好的管理网页的业务逻辑,以及按照自己的需求去使用各种模块,并且可以让每个开发者都能设计自己想要的模块以及去使用别人的模块代码。 @有了模块的概念,但为了让大家能方便的加载各种模块,因此需要一套编写模块的规范,而目前通行的Javascript的模板规范共有两种:CommonJS 和 AMD

CommonJS

CommonJS的历史渊源: nodejs项目的诞生,将javascript语言用于服务器编程。由于服务器端开发十分复杂,需要与OS以及其他应用程序互动,模块化的理念对服务器端开发是必需的。而nodejs的模块系统,就是参照CommonJS规范实现的

@因此我理解CommonJS即为服务器端模块的规范。 CommonJS的规范: 根据CommonJS规范,一个单独的文件就是一个模块。加载模块使用require方法,该方法读取一个文件并执行,最后返回文件内部的exports对象。下面就是一个简单的模块文件example.js

console.log("example.js");
exports.message = "hi";
exports.say = function (){
    console.log("hello");
};

使用require方法,加载example.js. 这时变量example就对应模块中的exports对象

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

AMD规范

AMD的历史渊源:

CommonJS规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。AMD规范则是非同步加载模块,允许指定回调函数。由于Node.js主要用于服务器编程,模块文件一般都已经存在于本地硬盘,所以加载起来比较快,不用考虑非同步加载的方式,所以CommonJS规范比较适用。但是,如果是浏览器环境,要从服务器端加载模块,这时就必须采用非同步模式,因此浏览器端一般采用AMD规范。

@因此我理解AMD即为能在客户端环境,并且能兼容服务器端模块的一种模块规范。

AMD的模块定义:

AMD规范使用define方法定义模块,下面是一个例子:

define(['package/lib'], function(lib){
    function foo(){
        lib.log('hello world');
    }
    return{
        foo: foo
    };
});

Define第一个参数表达依赖的模块数组,第二个为加载完依赖的模块数组后,模块执行的函数

AMD的模块加载定义:跟CommonJS 一样,AMD也采用require()语句来加载模块,但是与CommonJS不同的是,它要求有两个参数:

require([module], callback);

第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。AMD形式,就是下面这样:

require(['package/moduleA'], function(moduleA){
    moduleA.add(2, 3);
});

modleA.add()与moduleA模块加载不是同步的,十分适合浏览器的环境

AMD优缺:

AMD 运行时核心思想是「Early Executing」,也就是提前执行依赖 AMD 的这个特性有好有坏:   首先,尽早执行依赖可以尽早发现错误。上面的代码中,假如 a 模块中抛异常,那么 main.js 在调用 factory 方法之前一定会收到错误,factory 不会执行;如果按需执行依赖,结果是:   1、没有进入使用 a 模块的分支时,不会发生错误;   2、出错时,main.js 的 factory 方法很可能执行了一半。      另外,尽早执行依赖通常可以带来更好的用户体验,也容易产生浪费。例如模块 a 依赖了另外一个需要异步加载数据的模块 b,尽早执行 b 可以让等待时间更短,同时如果 b 最后没被用到,带宽和内存开销就浪费了;这种场景下,按需执行依赖可以避免浪费,但是带来更长的等待时间。    引用AMD的Javscript库: 目前,主要有两个Javascript库实现了AMD规范:require.js和curl.js

RequireJS与SeaJS

@根据诞生的时间,先有了Requirejs,然后再诞生了SeaJS。但其实requirejs 和 seajs其实都是模块加载器,只是遵循的模块规范不同,加载机制有所不同。

@在讲解之前,我先说明下模块加载器出现之前存在的两个问题:

  • 最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了。后来,由于代码越来越多,一个文件很难管理并进行维护,必须分成多个文件,依次加载。而一次加载多个js文件有很大的弊端---加载的时候,浏览器会停止网页的渲染,加载文件越多,而网页失去响应的时间就会越长。
  • 由于出现了模块的定义,许多js文件之间存在着依赖关系,因此必须严格保证加载的顺序(即依赖性最大的一定要放到最后加载)

由此可以看出模块加载器的作用,主要是为了解决两个问题: 实现js文件的异步加载,避免网页失去响应 管理模块之间的依赖性,便于代码的编写和维护

RequireJS 与 SeaJS 的异同:

@异同摘录知乎大神的讲法,感觉比较具体和准确 相同之处:   RequireJS 和 SeaJS 都是模块加载器,倡导的是一种模块化开发理念,核心价值是让 JavaScript的模块化开发变得更简单自然。 不同之处:

  • 定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。SeaJS 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 服务器端。
  • 遵循的规范不同。RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范。规范的不同,导致了两者 API 的不同。SeaJS 更简洁优雅,更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
  • 社区理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。SeaJS 不强推,采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
  • 代码质量有差异。RequireJS 是没有明显的 bug,SeaJS 是明显没有 bug。
  • 对调试等的支持有差异。SeaJS 通过插件,可以实现 Fiddler 中自动映射的功能,还可以实现自动 combo 等功能,非常方便。RequireJS 无这方面的支持。

总结:

前端模块化的诞生,大大促进我们前端的发展。前端模块化是web前端需掌握的基础知识之一。

参考:

http://www.douban.com/note/283566440/

http://wiki.commonjs.org/wiki/Modules/1.1

http://seajs.org/docs/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

像iPhone一样好玩的Web服务器: Caddy

据Netcraft今年5月份放出了一篇统计文章中,Apache、Nginx和微软的IIS分别以45.61%、20.22%和7.83%市场占有率依然排在“活跃网站...

50611
来自专栏JAVA高级架构

历经8年双11流量洗礼,淘宝开放平台如何攻克技术难关?

淘宝开放平台(open.taobao.com)是阿里系统与外部系统通讯的最重要平台,每天承载百亿级的API调用,百亿级的消息推送,十亿级的数据同步,经历了8年双...

1222
来自专栏北京马哥教育

15个最受欢迎的Python开源框架

我们从GitHub中整理出了15个最受欢迎的Python开源框架,这些框架包括事件I/O、OLAP、Web开发、高性能网络通信、测试、爬虫等。   1. Dja...

3167
来自专栏微信终端开发团队的专栏

微信终端跨平台组件 mars 系列(一):高性能日志模块xlog

mars 是微信官方的终端基础组件,是一个使用 C++ 编写的业务性无关,平台性无关的基础组件。本文章是 mars 系列的第一篇:高性能跨平台日志模块。

3690
来自专栏腾讯大数据的专栏

分布式高可靠消息中间件-Hippo

前言 随着大数据产品的日渐丰富以及数据应用场景需求的增加,TDBank作为腾讯大数据平台的数据接入环节的位置也越发显得重要(见下图)。截止目前为止TDBank...

3026
来自专栏性能与架构

分布式消息队列 Kafka

Kafka是一个高吞吐量的、分布式的消息系统,由Linkedin开发,开发语言为scala 具有高吞吐、可扩展、分布式等特点 适用场景 活动数据统计 活...

3775
来自专栏思考的代码世界

基础篇|PHP如何解决网站大流量和高并发

并发,在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行

7053
来自专栏大闲人柴毛毛

常用的分布式事务解决方案

众所周知,数据库能实现本地事务,也就是在同一个数据库中,你可以允许一组操作要么全都正确执行,要么全都不执行。这里特别强调了本地事务,也就是目前的数据库只能支持...

2.9K10
来自专栏数据和云

【新书连载】应用无法连接数据库问题分析

编辑说明:《Oracle性能优化与诊断案例精选》出版以来,收到很多读者的来信和评论,我们会通过连载的形式将书中内容公布出来,希望书中内容能够帮助到更多的读者朋友...

3105
来自专栏Java架构师进阶

浅谈Nginx负载均衡与F5的区别

笔者最近在负责某集团网站时,同时用到了Nginx与F5,如图所示,负载均衡器F5作为处理外界请求的第一道“墙”,将请求分发到web服务器后,web服务器上的Ng...

851

扫码关注云+社区