GitHub:我们是这样弃用jQuery的
摘要: 技术债清理流程指南。
- 原文:Removing jQuery from GitHub.com frontend
 - 译文:GitHub:我们为什么会弃用jQuery?
 - 作者:GitHub 前端工程团队
 - 译者:无明
 - 编辑:覃云
 
最近,我们将jQuery 完全从 GitHub.com 的前端代码中移除了,这标志着我们数年来逐步移除 jQuery这个渐进式的过程终于结束了,这对我们来说是一件里程碑式的事件。这篇文章将介绍过去我们是如何依赖上jQuery的,随着时间地推移,我们意识到不再需要它,但到最后我们并没有使用另一个库或框架取代它,而是使用标准的浏览器API实现了我们所需要的一切。
早期,jQuery对我们意义重大
GitHub.com在2007年底开始使用jQuery 1.2.1,那是谷歌发布 Chrome 浏览器的前一年。当时还没有通过CSS选择器来查询DOM元素的标准方法,也没有动态渲染元素的样式的标准方法,而Internet Explorer的XMLHttpRequest接口与其他很多API一样,在浏览器之间存在不一致性问题。
jQuery让DOM操作、创建动画和“AJAX”请求变得相当简单,基本上,它让Web开发人员能够创建更加现代化的动态Web体验。最重要的是,使用jQuery为一个浏览器开发的代码也适用于其他浏览器。在GitHub的早期阶段,jQuery让小型的开发团队能够快速进行原型设计并开发出新功能,而无需专门针对每个Web浏览器调整代码。
基于jQuery简单的接口所构建的扩展库也成为GitHub.com前端的基础构建块:pjax和facebox。
我们将永远不会忘记John Resig和jQuery贡献者创建和维护的这样一个有用的基本库。
后来的Web标准
多年来,GitHub成长为一家拥有数百名工程师的公司,并逐渐成立了一个专门的团队,负责 JavaScript代码的规模和质量。我们一直在排除技术债务,有时技术债务会随着依赖项的增多而增长,这些依赖项在一开始会为我们带来一定的价值,但这些价值也随着时间的推移而下降。
我们可以将jQuery与现代浏览器支持的Web标准的快速演化进行比较:
- $(selector)模式可以使用querySelectorAll()来替换;
 - 现在可以使用Element.classList来实现CSS类名切换;
 - CSS现在支持在样式表中而不是在JavaScript中定义可视动画;
 - 现在可以使用Fetch Standard执行$.ajax请求;
 - addEventListener()接口已经足够稳定,可以跨平台使用;
 - 我们可以使用轻量级的库来封装事件委托模式;
 - 随着JavaScript语言的发展,jQuery提供的一些语法糖已经变得多余。
 
另外,链式语法不能满足我们想要的编写代码的方式。例如:
$('.js-widget')
  .addClass('is-loading')
  .show()
这种语法写起来很简单,但是根据我们的标准,它并不能很好地传达我们的意图。作者是否期望在当前页面上有一个或多个js-widget元素?另外,如果我们更新页面标记并意外遗漏了js-widget类名,浏览器是否会抛出异常会告诉我们出了什么问题?默认情况下,当没有任何内容与选择器匹配时,jQuery会跳过整个表达式,但对我们来说,这是一个bug。
最后,我们开始使用Flow来注解类型,以便在构建时执行静态类型检查,并且我们发现,链式语法不适合做静态分析,因为几乎所有jQuery方法返回的结果都是相同的类型。我们当时之所以选择Flow,是因为@flow weak模式等功能可以让我们逐步将类型应用于无类型的代码库上。
总而言之,移除jQuery意味着我们可以更多地依赖Web标准,让MDN Web文档成为前端开发人员事实上的默认文档,在将来可以维护更具弹性的代码,并且可以将30KB的依赖从我们的捆绑包中移除,加快页面的加载速度和JavaScript的执行速度。
逐步解耦
虽然定下了最终目标,但我们也知道,分配所有资源一次性移除 jQuery 是不可行的。这种匆匆忙忙的做法可能会导致网站功能出现回归。相反,我们采取了以下的策略:
- 设定指标,跟踪整一行代码调用jQuery的比率,并监控指标走势随时间变化的情况,确保它保持不变或下降,而不是上升。
 

我们不鼓励在任何新代码中导入jQuery。为了方便自动化,我们创建了eslint-plugin-jquery,如果有人试图使用jQuery功能,例如 $.ajax,CI检查将会失败。
旧代码中存在大量违反eslint规则的情况,我们在代码注释中使用特定的eslint-disable 规则进行了注解。看到这些代码的读者,他们都该知道,这些代码不符合我们当前的编码实践。
我们创建了一个拉请求机器人,当有人试图添加新的eslint-disable规则时,会对拉取请求留下评论。这样我们就可以尽早参与代码评审,并提出替代方案。
很多旧代码使用了pjax和facebox插件,所以我们在保持它们的接口几乎不变的同时,在内部使用JS重新实现它们的逻辑。静态类型检查有助于提升我们进行重构的信心。
很多旧代码与rails-behavior发生交互,我们的Ruby on Rails适配器几乎是“不显眼的”JS,它们将 AJAX 生命周期处理器附加到某些表单上:
// 旧方法
  $(document).on('ajaxSuccess', 'form.js-widget', function(event, xhr, settings, data) {
    // 将响应数据插入到 DOM 中
  })
我们选择触发假的ajax*生命周期事件,并保持这些表单像以前一样异步提交内容,而不是立即重写所有调用,只是会在内部使用fetch()。
我们自己维护了jQuery的一个版本,每当发现我们不再需要jQuery的某个模块的时候,就会将它从自定义版本中删除,并发布更轻量的版本。例如,在移除了jQuery的CSS伪选择器之后(如:visible 或:checkbox)我们就可以移除Sizzle模块了,当所有的$.ajax调用都被 fetch()替换时,就可以移除AJAX模块。这样做有两个目的:加快JavaScript执行速度,同时确保不会有新代码试图使用已移除的功能。
我们根据网站的分析结果尽快放弃对旧版本Internet Explorer的支持。每当某个 IE 版本的使用率低于某个阈值时,我们就会停止向它提供JavaScript支持,并专注支持更现代的浏览器。尽早放弃对IE 8和IE 9的支持对于我们来说意味着可以采用很多原生的浏览器功能,否则的话有些功能很难通过polyfill来实现。
作为GitHub.com前端功能开发新方法的一部分,我们专注于尽可能多地使用常规HTML,并且逐步添加JavaScript行为作为渐进式增强。因此,那些使用JS增强的Web表单和其他UI元素通常也可以在禁用JavaScript的浏览器上正常运行。在某些情况下,我们可以完全删除某些遗留的代码,而不需要使用JS重写它们。
经过多年的努力,我们逐渐减少对jQuery的依赖,直到没有一行代码引用它为止。
自定义元素
近年来一直在炒作一项新技术,即自定义元素——浏览器原生的组件库,这意味着用户无需下载、解析和编译额外的字节。
从 2014 年开始,我们已经基于 v0 规范创建了一些自定义元素。然而,由于标准仍然在不断变化,我们并没有投入太多精力。直到 2017 年,Web Components v1 规范发布,并且 Chrome 和 Safari 实现了这一规范,我们才开始更广泛地采用自定义元素。
在移除 jQuery 期间,我们也在寻找用于提取自定义元素的模式。例如,我们将用于显示模态对话框的 facebox 转换为
我们的渐进式增强理念也延伸到了自定义元素上。这意味着我们将尽可能多地保留标记内容,然后再标记上添加行为。例如,默认显示原始时间戳,它被升级成可以将时间转换为本地时区,而对于
以下是实现自定义元素的示例:
// local-time 根据用户的当前时区显示时间。
//
// 例如:
//   <local-time datetime="2018-09-06T08:22:49Z">Sep 6, 2018</local-time>
//
class LocalTimeElement extends HTMLElement {
  static get observedAttributes() {
    return ['datetime']
  }
  attributeChangedCallback(attrName, oldValue, newValue) {
    if (attrName === 'datetime') {
      const date = new Date(newValue)
      this.textContent = date.toLocaleString()
    }
  }
}
if (!window.customElements.get('local-time')) {
  window.LocalTimeElement = LocalTimeElement
  window.customElements.define('local-time', LocalTimeElement)
}
我们很期待 Web 组件的 Shadow DOM。Shadow DOM 的强大功能为 Web 带来了很多可能性,但也让 polyfill 变得更加困难。因为使用 polyfill 会导致性能损失,因此在生产环境中使用它们是不可行的。
参考
关于Fundebug
Fundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、React Native、Node.js和Java实时BUG监控。 自从2016年双十一正式上线,Fundebug累计处理了7亿+错误事件,得到了Google、360、金山软件、百姓网等众多知名用户的认可。欢迎免费试用!

版权声明
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2018/11/23/removing-jquery-from-github-frontend/
GitHub:我们是这样弃用jQuery的的更多相关文章
- 2019 年了,为什么我还在用 jQuery?
		
译者按: 看来 jQuery 还是有一些用武之地的. 原文: Why I'm Still Using jQuery in 2019 译者: Fundebug 为了保证可读性,本文采用意译而非直译.翻译 ...
 - Jquery操作cookie,实现简单的记住用户名的操作
		
一.jquery.cookie.js介绍 jquery.cookie.js是一个基于jquery的插件,一个轻量级的cookie 插件,可以读取.写入.删除 cookie. jquery.cook ...
 - [译] jQuery 3 有哪些新东西
		
转自:https://github.com/cssmagic/blog/issues/59 jQuery 的横空出世,至今已有十个年头了,而它的长盛不衰显然不是没有理由的.jQuery 提供了极为友好 ...
 - jquery.fileupload插件的简易使用日志
		
来源:http://yixiandave.iteye.com/blog/1897330 本文内容主要包含fileupload插件传递参数和取回服务器返回数据的方法 jquery.fileupload官 ...
 - jQuery Validate 表单验证插件----Validate简介,官方文档,官方下载地址
		
一. jQuery Validate 插件的介绍 jQuery Validate 插件为表单提供了强大的验证功能,让客户端表单验证变得更简单,同时提供了大量的定制选项,满足应用程序各种需求.该插件捆 ...
 - jQuery组件写法
		
知识点: 什么是插件 jQuery插件的模式 jQuery插件的Lightweight Start模式(入门级插件模式) 8.1 插件(Plug-in) “插件”这个关键字,估计大家在日常生活中经常有 ...
 - jquery 银行卡号验证
		
具体参考:https://github.com/jondavidjohn/payform 插件js: jquery.payform.js 具体操作 alert($.payform.validateCa ...
 - jquery $ dollar符号用法总结
		
参考:https://github.com/chyingp/blog/blob/master/jquery/jQuery%E6%BA%90%E7%A0%81-%E7%BE%8E%E5%85%83$%E ...
 - 使用JQuery.lettering.js实现多行文本样式自定义
		
前几天一位在广告公司的朋友发来求助,说:“有一个项目要求实现对字符串进行动态拆分,然后对拆分出的字符分别使用不同的样式效果...”,听到这个需求,我内心有点不屑,这有何能,最多五分钟搞定啊~~ 于是我 ...
 
随机推荐
- Android 展示控件之Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的关系
			
一.Surface Surface在SDK的文档中的描述是这样的:Handle onto a raw buffer that is being managed by the screen compos ...
 - Java核心技术卷一基础知识-第14章-多线程-读书笔记
			
第 14 章 多线程 本章内容: * 什么是线程 * 中断线程 * 线程状态 * 线程属性 * 同步 * 阻塞队列 * 线程安全的集合 * Collable与Future * 执行器 * 同步器 * ...
 - java小白之面向对象
			
面向对象 面相对象(oop)和面向过程(pop)通常一起说,一个是更加关注过程,事力亲为,而面向对象更加注重结果,所以说,面向对象更加是一种思想,它贯穿整个java,以上帝视角来看整个功能需求,简化开 ...
 - 微信小程序wx.request接口
			
微信小程序wx.request接口 wx.request是小程序客户端与服务器端交互的接口 HTTPS 请求 一个微信小程序,只能同时(同时不能大于5个)有5个网络请求 wx.request(OBJE ...
 - python 反转一个字符串
			
old_str = 'abcd' new_str1 = old_str[::-1] print(new_str1) new_str2 = ''.join(reversed(old_str)) prin ...
 - 基于 jq 实现拖拽上传 APK 文件,js解析 APK 信息
			
技术栈 jquery 文件上传:jquery.fileupload,github 文档 apk 文件解析:app-info-parser,github 文档 参考:前端解析ipa.apk安装包信息 - ...
 - 本地Oracle客户端11g升级12c导致PowerCenter无法连接ODBC数据源
			
问题: 本地Oracle客户端由11g-32bit升级为12c-64bit时,在PowerCenter Designer使用原来的ODBC连接导入数据库表时,发生如下错误: 原因: 原oracle11 ...
 - 国内使用google搜索引擎
			
百度搜索 "谷歌访问助手",点击第一个搜索结果,如下: 或者直接点击链接:http://www.ggfwzs.com/ ,然后点击相应的浏览器下载谷歌访问助手,解压,将解压好的谷 ...
 - app测试之专项测试
			
专项测试包含很多东西,安装.升级.卸载.性能.安全.网络.随机等等,这些都属于专项测试 一个app的正常到用户手里使用,功能是最基础的测试,专项测试测试主要的. 下面介绍一些常用的专项测试: 1.多任 ...
 - chrome强制刷新,非ctrl+f5
			
开发时,经常有ctrl+f5无法做到真正的强制刷新,以下可以帮到你 Ctrl+Shift+Del 清除Google浏览器缓存的快捷键 Ctrl+Shift+R 重新加载当前网页而不使用缓存内容