浅谈前端模块化

  • 模块化编程
  • 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 条评论
登录 后参与评论

相关文章

来自专栏软件开发

CSS3与页面布局学习总结(二)——Box Model、边距折叠、内联与块标签、CSSReset

一、盒子模型(Box Model) 盒子模型也有人称为框模型,HTML中的多数元素都会在浏览器中生成一个矩形的区域,每个区域包含四个组成部分,从外向内依次是:外...

23110
来自专栏张善友的专栏

Microsoft .NET Framework 3.5中文组件包

.NET Framework 3.0 中增加了不少新功能,例如 Windows Workflow Foundation (WF)、Windows Communi...

1887
来自专栏ASP.NETCore

ASP.NET Core中使用Razor视图引擎渲染视图为字符串

  在有些项目需求上或许需要根据模板生产静态页面,那么你一样可以用Razor语法去直接解析你的页面从而把解析的页面生成静态页,这样的使用场景很多,不限于生成静态...

1314
来自专栏我分享我快乐

水平线上涨loading实现原理

前期准备:需要一张水平线荡漾图片,格式为png或svg 代码实现如下: <!doctype html> <html> <head> <script src="...

29210
来自专栏恰同学骚年

新时期的.NET程序员学习路线图

681
来自专栏小狼的世界

封装内容和功能 – YUI TabView使用小记

本文主要内容取自 Caridy Patino 在2008年发布的文章,原文中使用的是YUI2,笔者对例子做了一些更新,均使用了YUI3.1.1,文章中讨论的这个...

602
来自专栏圣杰的专栏

Asp.net mvc 知多少(一)

本系列主要翻译自《ASP.NET MVC Interview Questions and Answers 》- By Shailendra Chauhan,想...

1917
来自专栏Java Edge

CSS 全解析实战(八)-Bootstrap1 Bootstrap介绍2 Bootstrap基本用法3 Bootstrap JS组件

792
来自专栏.NET开发者社区

(码友推荐)2018-07-25 .NET及相关开发资讯速递

3.多人协同开发如何保证代码质量!看看这篇《理想中的Jenkins+Sonar+Github代码质量管理》

892
来自专栏张善友的专栏

Mono 3.2.7发布,JIT和GC进一步改进

Mono 3.2.7已经发布,带来了很多新特性,如改进的JIT、新的面向LINQ的解释器以及使用了64位原生指令等等。 这是一次主要特性发布,累积了大约5个月的...

1736

扫码关注云+社区