最近,我们将 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(https://github.com/defunkt/jquery-pjax)和 facebox(https://github.com/defunkt/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 是不可行的。这种匆匆忙忙的做法可能会导致网站功能出现回归。相反,我们采取了以下的策略:

1. 设定指标,跟踪整一行代码调用 jQuery 的比率,并监控指标走势随时间变化的情况,确保它保持不变或下降,而不是上升。

2. 我们不鼓励在任何新代码中导入 jQuery。为了方便自动化,我们创建了 eslint-plugin-jquery(https://github.com/dgraham/eslint-plugin-jquery),如果有人试图使用 jQuery 功能,例如 $.ajax,CI 检查将会失败。

3. 旧代码中存在大量违反 eslint 规则的情况,我们在代码注释中使用特定的 eslint-disable 规则进行了注解。看到这些代码的读者,他们都该知道,这些代码不符合我们当前的编码实践。

4. 我们创建了一个拉请求机器人,当有人试图添加新的 eslint-disable 规则时,会对拉取请求留下评论。这样我们就可以尽早参与代码评审,并提出替代方案。

5. 很多旧代码使用了 pjax 和 facebox 插件,所以我们在保持它们的接口几乎不变的同时,在内部使用 JS 重新实现它们的逻辑。静态类型检查有助于提升我们进行重构的信心。

6. 很多旧代码与 rails-behavior 发生交互,我们的 Ruby on Rails 适配器几乎是“不显眼的”JS,它们将 AJAX 生命周期处理器附加到某些表单上:

// 旧方法$(document).on('ajaxSuccess', 'form.js-widget', function(event, xhr, settings, data) {// 将响应数据插入到 DOM 中})

7. 我们选择触发假的 ajax* 生命周期事件,并保持这些表单像以前一样异步提交内容,而不是立即重写所有调用,只是会在内部使用 fetch()。

8. 我们自己维护了 jQuery 的一个版本,每当发现我们不再需要 jQuery 的某个模块的时候,就会将它从自定义版本中删除,并发布更轻量的版本。例如,在移除了 jQuery 的 CSS 伪选择器之后(如:visible 或:checkbox)我们就可以移除 Sizzle 模块了,当所有的 $.ajax 调用都被 fetch() 替换时,就可以移除 AJAX 模块。

这样做有两个目的:加快 JavaScript 执行速度,同时确保不会有新代码试图使用已移除的功能。

9. 我们根据网站的分析结果尽快放弃对旧版本 Internet Explorer 的支持。每当某个 IE 版本的使用率低于某个阈值时,我们就会停止向它提供 JavaScript 支持,并专注支持更现代的浏览器。尽早放弃对 IE 8 和 IE 9 的支持对于我们来说意味着可以采用很多原生的浏览器功能,否则的话有些功能很难通过 polyfill 来实现。

10. 作为 GitHub.com 前端功能开发新方法的一部分,我们专注于尽可能多地使用常规 HTML,并且逐步添加 JavaScript 行为作为渐进式增强。因此,那些使用 JS 增强的 Web 表单和其他 UI 元素通常也可以在禁用 JavaScript 的浏览器上正常运行。在某些情况下,我们可以完全删除某些遗留的代码,而不需要使用 JS 重写它们。

经过多年的努力,我们逐渐减少对 jQuery 的依赖,直到没有一行代码引用它为止。

自定义元素

近年来一直在炒作一项新技术,即自定义元素——浏览器原生的组件库,这意味着用户无需下载、解析和编译额外的字节。

从 2014 年开始,我们已经基于 v0 规范创建了一些自定义元素。然而,由于标准仍然在不断变化,我们并没有投入太多精力。直到 2017 年,Web Components v1 规范发布,并且 Chrome 和 Safari 实现了这一规范,我们才开始更广泛地采用自定义元素。

在移除 jQuery 期间,我们也在寻找用于提取自定义元素的模式。例如,我们将用于显示模态对话框的 facebox 转换为<details-dialog>元素(https://github.com/github/details-dialog-element)。

我们的渐进式增强理念也延伸到了自定义元素上。这意味着我们将尽可能多地保留标记内容,然后再标记上添加行为。例如,<local-time>默认显示原始时间戳,它被升级成可以将时间转换为本地时区,而对于<details-dialog>,当它被嵌在 <details>元素中时,可以在不使用 JavaScript 的情况下具备交互性,它被升级成具有辅助增强功能。

以下是实现<local-time>自定义元素的示例:

// 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 = LocalTimeElementwindow.customElements.define('local-time', LocalTimeElement)
}

我们很期待 Web 组件的 Shadow DOM。Shadow DOM 的强大功能为 Web 带来了很多可能性,但也让 polyfill 变得更加困难。因为使用 polyfill 会导致性能损失,因此在生产环境中使用它们是不可行的。

原文地址:http://www.techug.com/post/why-we-removing-jquery-from-github-frontend.html

GitHub:我们为什么会弃用jQuery?相关推荐

  1. soap 版本可能不匹配: 出现意外的 envelope 命名空间_Collaboratorv11.5版本上新!GitHub Polling集成被弃用!...

    Collaborator是一款功能全面的代码审查工具.它的代码审查可以为开发测试人员和管理者提供帮助,生产出高质量的代码. 我们很高兴的告诉大家,Collaborator更新至11.5版本,Diff ...

  2. jquery获取浏览器版本号_前端为什么弃用jQuery?有这六个原因

    点击右上方红色按钮关注"小郑搞码事",每天都能学到知识,搞懂一个问题! 前端为什么都不再使用jQuery?这个问题其实也非常好理解,首先,你得知道jQuery给我们解决了什么问题. ...

  3. (转)GitHub 被微软收购后的 52 天,改版并放弃了 jQuery!

    上个月,『全球最大同性交友平台』GitHub 被微软以 75 亿美元(折合人民币 480 亿)的价格正式收购,这一事件引发诸多程序员担忧: 微软收购之后,Github 是否会将不再开源? 为防范于未然 ...

  4. GitHub:为什么我们最终选择放弃了 jQuery

    [CSDN编者按]7月17日,GitHub改版并放弃了jQuery, 这对于GitHub来说,绝对是一件可以载入公司史册的大事. 今天的文章中,四位参与改版和弃用JQuery的GitHub工程师,将介 ...

  5. GitHub 被微软收购后的 52 天,改版并放弃了 jQuery !

    上个月,『全球最大同性交友平台』GitHub 被微软以 75 亿美元(折合人民币 480 亿)的价格正式收购,这一事件引发诸多程序员担忧: 微软收购之后,Github 是否会将不再开源? 为防范于未然 ...

  6. 和 jQuery 说再见!Bootstrap 5 将移除对其依赖

    继去年 7 月,GitHub 前端团队公开表示在 GitHub 网站重构过程中弃用 jQuery,并改用原生的 JS 之后,来自 Twitter 的知名前端框架 Bootstrap 团队于近日也表示, ...

  7. [译] 2019 年了,为什么我还在用 jQuery?

    译者按: 看来 jQuery 还是有一些用武之地的. 原文: Why I'm Still Using jQuery in 2019 译者: Fundebug 为了保证可读性,本文采用意译而非直译.翻译 ...

  8. jQuery日期选择器插件date-input

    官网:http://jonathanleighton.com/projects/date-input/ 下载: http://ajax.googleapis.com/ajax/libs/jquery/ ...

  9. jquery ajax中使用jsonp的限制[转]

    转自: http://www.cnblogs.com/dudu/archive/2012/12/04/jquery_ajax_jsonp.html jsonp 解决的是跨域 ajax 调用的问题.为什 ...

最新文章

  1. WIN10python3.7配置MaskRCNN环境及demo测试(tensorflow-gpu1.x)
  2. mysql update 有中文_MySQL Update语句一个非常经典的“坑”
  3. java 基础之 null 与 “”
  4. Yum database disk image is malformed 错误
  5. 数据管理 - 每天5分钟玩转 Docker 容器技术(147)
  6. java判断当前时间距离第二天凌晨的秒数
  7. 5001 boost之bind库函数
  8. HDU 5586 Sum (预处理 + 动态规划)
  9. Python知识点之Python进阶
  10. Macbook Pro M1(macOS 12.0)读取NTFS移动硬盘方法
  11. 【科技检索报告】基于大规模浮动车GPS数据的实时地图匹配方法
  12. [Cmder] ConEmu报错,用bandzip代替7zip或者winRAR
  13. Google Earth Engine——飓风最佳轨迹数据库(HURDAT2)。大西洋盆地1851-2018年。
  14. 计算机影响因子10.0什么水平,论文的影响因子是什么?由什么决定?_1 论文影响因子10.0什么水平...
  15. 远程连接MySQL, 10038问题
  16. mac实用小技巧之解压.xip文件
  17. 闭锁java_实例讲解Java并发编程之闭锁
  18. hass智能 小米扫地机器人_搭建智能家居第三篇:小米系列接入homeassistant的教程分享...
  19. 证件照怎么自己P图?证件照拍照攻略 记得收藏
  20. Android MagicIndicator系列之一 —— 使用MagicIndicator打造千变万化的ViewPager指示器

热门文章

  1. 转化关系模型外键_网站数据分析:流量运营分析模型拯救你的广告流量
  2. 支持专业设计师的高端样机素材网
  3. 圣诞海报简单设计技巧|装饰气氛PNG免抠素材
  4. 化妆品包装新趋势|视觉模型样机包装模板,让你茅塞顿开
  5. android中activity布局,Android中登录布局展示Activity
  6. mysql 停数据库_mysql数据库突然停了
  7. javascript 无法修改 数组中对象_如何使用JavaScript中的Date对象
  8. js 设置password placeholder样式_150+ 个优质的 Node.js 包和资源
  9. python sqlite3 增删改查(最基本的增删改查)
  10. 项目中的软件需求说明书的访谈部分