jQuery2.x源码解析(构建篇)

jQuery2.x源码解析(设计篇)

jQuery2.x源码解析(回调篇)

jQuery2.x源码解析(缓存篇)

笔者阅读了园友艾伦 Aaron的系列博客《jQuery源码分析系列》,跑艾伦的部分代码后,感觉仍然不够解渴,对jQuery依旧一知半解,产生了很多问题。阅读源码博客已经无法解决这些问题,所以笔者决定亲自查看jQuery源码,解除心中的疑问。阅读的形式属于自问自答,笔者会提出疑问,然后亲自解答(吐槽:感觉有点像一休哥和将军大人>_<)。

问题的来源主要有3种:

1.在阅读园友艾伦博客后产生的疑问

2.以前就有疑问,艾伦博客却没有解答或者解释不够明白

3.阅读源码的过程中产生的疑问

所以这个jQuery源码解析系列并非教程,而是笔者的学习jQuery源码的笔记,因此才会采取问答这种不系统的形式。如果大家想系统学习jQuery源码,还请仔细阅读艾伦 Aaron的博客;或是直接阅读jQuery在gitbub上的源码(目前的master版本是2.2-stable,笔者阅读的也是这个版本的代码)。如果在阅读后也和笔者一样,对一些内容存在疑问,可以看看笔者的系列博客,看看你有没有你疑惑的问题;如果没有就发问给我,我们一起思考答案。


提问:如何构建jQuery的源码

在我开始阅读jQuery的源码时,发现源代码本身是有模块化的,而艾伦 Aaron阅读的版本没有,他是直接阅读的dist后的代码。那么jQuery是如何构建源代码的呢?

答:阅读jQuery在github上的README.md文件,里面已经说得非常清楚了。先安装git客户端和nodejs及npm。然后将github上的资源克隆到本地,找一个目录,然后打开命令行,输入git的clone命令:

git clone git://github.com/jquery/jquery.git

本地就会克隆出jQuery的源代码:

然后进入该目录下,在命令行上运行如下命令,jQuery就会自动安装npm模块,并构建jQuery了。

npm run build

最后在dist目录中,会构建出我们想要的jQuery文件了。


提问:git上的jQuery目录结构是怎样的

答:具体目录结构可以看上图,这里逐个介绍一下各个目录和文件的作用:

.github git相关目录
build 构建相关的脚本文件,笔者大概阅读了一下,主要是创建两个Grunt任务,负责构建(bulid)和输出(dist)
dist 输出构建后的文件,主要是jquery.js和jquery.min.js,以及jquery.min.map。这些就是我们最终使用的js文件了
external 放依赖的第三方代码,jQuery中最重的第三方库sizzle就在这里
node_modules nodejs的模块文件,构建时候安装的node非全局模块都放在这里,属性nodejs的小伙伴应该很清楚了
src jQuery自身的源代码的目录,这就是我们主要阅读的部分
test 单元测试用例
.babelrc Babel的配置文件
.editorconfig editorconfig的配置文件,editorconfig是帮助开发者在不同的编辑器和IDE之间定义和维护一致的代码风格的配置,很多ide都支持editorconfig的插件,使用这个就可以使各种ide下都能自动将代码显示成editorconfig约定的格式
.eslintignore eslint相关文件,配置不用于eslint语法检测的文件目录
.eslintrc.json eslint的配置文件。eslint和jshint比较像,可以认为是jshint的升级版,都是用来做语法检测的。
.gitattributes git相关文件,用于设置文件的对比方式
.gitignore git的配置文件,配置用于配置不需要加入版本管理的文件
.mailmap 貌似是一个邮件地址列表
.npmignore npm相关文件,配置哪些文件不需要被发布到npmjs.org
.npmrc npm的配置文件
.travis.yml Tarvis-CI的配置文件,持续集成用的,github整合了持续集成服务travis,每一次push之后,travis就会定时执行“npm test”来测试项目
AUTHORS.txt 贡献者名录
CONTRIBUTING.md 贡献代码指引
Gruntfile.js Grunt的配置文件
LICENSE.txt 授权协议
README.md github项目的说明文档
package.json npm的包文件

几个地方值得注意一下:

1.jQuery是用RequireJs做模块化工具的,所以jQuery的源代码是用AMD规范。AMD这个模块化规范主要活跃于基于浏览器的js模块管理,他有着异步加载、依赖前置等非常好的特性,当然用来做后端的代码模块管理也可以,但是笔者终究认为这里用AMD有点“大材小用”了。jQuery用AMD规范做模块化管理,可能是历史原因的影响,早些年模块化工具不像如今这么成熟。

2.jQuery是用Grunt构建的,jQuery自己做了构建的Grunt任务,具体代码可以参考build目录下的Grunt任务和Grunt的配置文件Gruntfile.js。基于Grunt,jQuery完成测试、构建、合并代码、压缩等工作,最终把构建好的文件拷贝到dist目录里面。

3.jQuery配置了npm包相关的配置,说明jQuery本身也被发布到了npmjs.org上,我们可以直接用npm安装jQuery。

4.jQuery有Babel的配置文件,那源代码是不是用ES6的语法呢?


提问:jQuery有Babel的配置文件,难道jQuery的源代码使用了ES6的语法?

答:答案是没有的,我们先不看Babel在Grunt里面的配置,直接试一下能不能在源代码中使用ES6。

先将源代码里面添加一条ES6的语法,然后执行构建。这时我们会发现构建的时候会报错,而且构建好的jQuery.js文件中ES6的语法也没有被转换为ES5的语法。这说明构建源代码的时候并没有启用Babel。

我们在来看Babel在Grunt里面的配置

babel: {
options: {
sourceMap: "inline",
retainLines: true
},
nodeSmokeTests: {
files: {
"test/node_smoke_tests/lib/ensure_iterability.js":
"test/node_smoke_tests/lib/ensure_iterability_es6.js"
}
}
},

可以看出,Babel仅是将测试用例中的冒烟测试用例做了转换,而源代码则不在被转换列表中。


提问:jQuery的源代码用的是AMD规范做模块化,为什么最终构建好的代码却没有AMD的语句呢?

阅读jQuery的源代码,我们可以很清楚的看到AMD规范的语句。

然后在dist里面的构建好的文件中,我们却找不到AMD规范语句的影子,jQuery是如何去掉了这些AMD语句呢?

答:起初笔者认为是用了一些Grunt上的插件,后来阅读了build里面的代码才发现,是在build里面使用正则将AMD语句去除。jQuery虽然是用的AMD做模块化,但是具体的代码结构还是有自己的一套策略,这个应该就是为了最后构建代码而考虑的。

src的根目录下,共有20多个js文件,很多js文件都有同名的目录与之对应。目录之中最特别的目录就是var目录,因为var目录并不存在与之对应的名为var.js的文件。

var这个名字和js的关键字var相同,这和这个目录这样命名肯定是有关系的。没错,jQuery在去除AMD语句的时候,发现如果是var目录里的文件的话,就会将其转换为“var 文件名 = AMD输出的对象”的形式。如下图:

define( 'var/arr',[],function() {
"use strict"; return [];
} ); define( 'var/document',[],function() {
"use strict"; return window.document;
} ); define( 'var/getProto',[],function() {
"use strict"; return Object.getPrototypeOf;
} ); ......

源代码的这几个模块最终会把构建为:

var arr = [];
var document = window.document;
var getProto = Object.getPrototypeOf;
......

而对于非“var”目录下的模块,jQuery会将define关键字等AMD相关的语句直接移除。其中sizzle模块更为特殊,jQuery在构建的时候还做了更多的操作,这里就不再细究了。

分析到这大家也能看出,jQuery这样构建是会破坏AMD各个模块的作用域的。我们之所以需要模块化我们的代码,一点是不希望我们把我们的内部(私有)变量声明到全局作用域中,而JavaScript是一种函数级作用域的语言,jQuery在构建的时候去掉了AMD的函数形式,这样所有模块的代码构建后的都会在同一个作用域里,所以在修改jQuery源代码的时候一定要小心,不要在作用域里面随意创建相同名称的变量,防止造成模块间的冲突。

以上就是jQuery去除AMD的过程。


提问:源码中经常有(#xxxx)这样的注释,他们是什么?

很多地方的注释,都有(#xxxx)的字样,如下:

// Use the original fragment for the last item
// instead of the first because it can end up
// being emptied incorrectly in certain situations (#8070).

答:这些是使用者提出的bug,jQuery的作者们根据bug修复的补丁。jQuery的源码在github上,bug大多都被提到了github上的issues里面,里面的每个bug都有个编号,就是#后面的几个数字,地址“https://github.com/jquery/jquery/issues/”加上这个编号就是bug所在的url了。进入这个url可以查看具体的bug说明和jQuery的作者们对于这个bug的修复情况。除了github的issues,jQuery在其官网也有一个buglist(“https://bugs.jquery.com/ticket/”),不过现在好像访问不了了,这个网站的后面同样有一串数字,#xxxx也有可能指的是这个网址里面bug的id。

了解了jQuery的构建过程后,我们就可以轻松愉快地浏览jQuery的源代码了。事实上如果jQuery构建的时候采用webpack这样的工具就简单多了。jQuery没有采用这样的工具可能也是历史原因,或者是出于进一步优化代码的目的。

jQuery2.x源码解析(构建篇)的更多相关文章

  1. jQuery2.x源码解析(缓存篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 缓存是jQuery中的又一核心设计,jQuery ...

  2. jQuery2.x源码解析(设计篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...

  3. jQuery2.x源码解析(回调篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 通过艾伦的博客,我们能看出,jQuery的pro ...

  4. jQuery2.x源码解析(DOM操作篇)

    jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) jQuery这个类库最为核心重要的功能就是DOM ...

  5. Shiro源码解析-Session篇

    上一篇Shiro源码解析-登录篇中提到了在登录验证成功后有对session的处理,但未详细分析,本文对此部分源码详细分析下. 1. 分析切入点:DefaultSecurityManger的login方 ...

  6. myBatis源码解析-类型转换篇(5)

    前言 开始分析Type包前,说明下使用场景.数据构建语句使用PreparedStatement,需要输入的是jdbc类型,但我们一般写的是java类型.同理,数据库结果集返回的是jdbc类型,而我们需 ...

  7. myBatis源码解析-反射篇(4)

    前沿 前文分析了mybatis的日志包,缓存包,数据源包.源码实在有点难顶,在分析反射包时,花费了较多时间.废话不多说,开始源码之路. 反射包feflection在mybatis路径如下: 源码解析 ...

  8. Spring源码解析 | 第二篇:Spring IOC容器之XmlBeanFactory启动流程分析和源码解析

    一. 前言 Spring容器主要分为两类BeanFactory和ApplicationContext,后者是基于前者的功能扩展,也就是一个基础容器和一个高级容器的区别.本篇就以BeanFactory基 ...

  9. myBatis源码解析-数据源篇(3)

    前言:我们使用mybatis时,关于数据源的配置多使用如c3p0,druid等第三方的数据源.其实mybatis内置了数据源的实现,提供了连接数据库,池的功能.在分析了缓存和日志包的源码后,接下来分析 ...

随机推荐

  1. ZIP压缩算法详细分析及解压实例解释

    最近自己实现了一个ZIP压缩数据的解压程序,觉得有必要把ZIP压缩格式进行一下详细总结,数据压缩是一门通信原理和计算机科学都会涉及到的学科,在通信原理中,一般称为信源编码,在计算机科学里,一般称为数据 ...

  2. 07.LoT.UI 前后台通用框架分解系列之——强大的文本编辑器

    LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...

  3. HTML5 progress和meter控件

    在HTML5中,新增了progress和meter控件.progress控件为进度条控件,可表示任务的进度,如Windows系统中软件的安装.文件的复制等场景的进度.meter控件为计量条控件,表示某 ...

  4. python笔记(持续更新)

    1.编译python遇到下面的编码问题:     SyntaxError: Non-ASCII character '\xe9' in file E:\projects\learn.py on lin ...

  5. 关于font-family

    在设置页面字体的时候,你会发现在 font-family 属性中会设置好多个字体,想看懂它们都是什么字体吗?不好意思,我不是搞设计的,我也不知道.那么,现在写的东西,只是对于一个前端人员来说,要了解的 ...

  6. 深入学习jQuery自定义插件

    原文地址:jQuery自定义插件学习 1.定义插件的方法 对象级别的插件扩展,即为jQuery类的实例增加方法, 调用:$(选择器).函数名(参数);      $(‘#id’).myPlugin(o ...

  7. maven 中snapshot版本和release版本的区别

    maven中的仓库分为两种,snapshot快照仓库和release发布仓库.snapshot快照仓库用于保存开发过程中的不稳定版本,release正式仓库则是用来保存稳定的发行版本.定义一个组件/模 ...

  8. 微信开发笔记(accesstoken)

    access_token分两种 一种是公众号权限获取用,调用cgi-bin接口 ,此种token一个公众号同时只有一个,用这一个就够了. 服务器最好缓存. 用这个token前提是用户关注了此公众号. ...

  9. 手机游戏渠道SDK接入工具项目分享(二)万事开头难

    一般接到任务后程序员们通常都开始着手进行技术调研了,但我这活是项目负责人.还有一大堆事情要先期准备,没人能帮忙. 一.人力配置 考虑的之前已经有一波人搞了大半年,但没有起色,先期也没有太大人力需求,所 ...

  10. NDK开发_笔记0

    自谷歌搜索退出中国以来,谷歌对全球第二大市场中国的态度一直保持冷淡.可是北京时间12月8日,谷歌2016开发者大会在北京召开,同时专门针对中国的谷歌开发者网站已经上线:https://develope ...