前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从GitHub.com放弃使用jQuery说起

从GitHub.com放弃使用jQuery说起

原创
作者头像
角落工程师
发布2022-05-10 14:40:26
8760
发布2022-05-10 14:40:26
举报
文章被收录于专栏:工程师养成记

今天聊一点js的东西。

js和物联网领域的关系不是很大,为什么要关心js呢?其实关系也不小,它主要是负责直接和用户交互的那部分,也就是前端,前端基本都是离不开js的,甚至有些CS架构的程序也用js,比如nodejs开发的客户端程序。

让我干唠是唠不出来什么的,因为咱没怎么用过js,只是最近在学习vue.js,看到了一篇GitHub官方在2018年发布的解释为什么放弃前端框架jQuery的文章,心血来潮,想读一遍,顺便翻译出来,以帮助理解。然而自己翻译一是太费时间,二是水平不够也翻不好,所以就借助机器翻译,先粗翻,我再润色。

原文链接:https://github.blog/2018-09-06-removing-jquery-from-github-frontend/

以下为译文:

从 GitHub.com 网站前端移除 jQuery

我们最近完成了一项里程碑式的工作,去除了GitHub.com 网站前端代码对 jQuery 的依赖。这标志着一个长达数年的与 jQuery 逐渐剥离的过渡工作的结束,我们现在已经能够完全删除该库。在这篇文章中,我们将解释一下我们最初是如何依赖 jQuery 的,又是如何意识到何时不再需要它的,并指出——我们能够使用标准浏览器 API 实现我们需要的一切(而不是用另一个库或框架替换它)。

为什么 jQuery 在早期有意义

GitHub.com 网站在 2007 年底将 jQuery 1.2.1 作为依赖引入。回顾当时的时间节点,谷歌在一年后才发布了其 Chrome 浏览器第一个版本。那时候还没有通过 CSS 选择器查询 DOM 元素的标准方法,也没有实现动画效果的标准方法,并且 IE 开创的 XMLHttpRequest 接口与许多其他 API 一样,存在浏览器兼容问题。

jQuery 使操作 DOM、实现动画效果和发起“AJAX”请求变得简单。它使 Web 开发人员能够创建更现代、更动态的网站页面,所以脱颖而出。最重要的是,使用 jQuery 在一个浏览器中构建的 JavaScript 功能通常也可以在其他浏览器中使用,它对浏览器的兼容问题处理的比较到位。在 GitHub 的早期,它的大部分功能仍在不断完善,jQuery 这些特性允许小型开发团队快速原型化他们的产品并推出新功能,而无需专门针对每个 Web 浏览器调整代码。

jQuery 简洁的接口还使开发插件扩展变得很简单,构建 GitHub.com 网站前端的 pjaxfacebox 就是两个基于 jQuery 开发的插件。

我们将永远铭记 John Resig 和 jQuery 贡献者创建和维护这样一个如此有用且在当时必不可少的库。

近些年的Web标准

这些年来,GitHub 成长为一家拥有数百名工程师的公司,并逐渐成立了一个专门的团队来负责把关 JavaScript 代码的规模和质量,这些代码会服务于 Web 浏览器。与此同时,我们也一直在寻找并排除技术债务,有时技术债务会随着依赖项的增多而增长,这些依赖项在一开始的时候给我们带来价值,但是随着时间推移和技术演变,价值会逐渐消失。

回到 jQuery 身上,我们将 jQuery API 与现代浏览器中支持的 Web API 进行了比较,并意识到一些问题:

  • $(selector)完全可以使用querySelectorAll()来替代;
  • css类名切换可以使用Element.classList实现;
  • css现在支持使用样式表而不是 JavaScript 定义动画;
  • 发起ajax请求可以使用Fetch Standard实现;
  • addEventListenner()接口足够稳定,支持跨平台使用;
  • 我们可以使用轻量级库轻松封装事件委托模式;
  • 随着JavaScript的发展,JQuery提供的语法糖显得越来越鸡肋。

此外,链接语法并不能满足我们未来想要编写代码的方式。例如:

代码语言:txt
复制
$('.js-widget')
  .addClass('is-loading')
  .show()

这种语法写起来很简单,但按照我们的标准,并不能很好地传达意图。作者是否期望此页面上有一个或多个 js-widget 元素?另外,如果我们更新页面并不小心遗漏了 js-widget 类名,浏览器是否会报异常通知我们出了问题?默认情况下,当没有匹配到选择器时,jQuery 会默默地跳过整个表达式,对我们来说,这是 bug 而不是功能。

最后,我们开始使用 Flow 注解以在构建时执行静态类型检查,然后我们发现链接语法不适合静态分析,因为几乎每个 jQuery 方法调用返回的结果都是相同的类型。我们之所以选择 Flow 是因为当时@flow weak 弱类型等功能使我们能够逐步有效地开始将类型应用到没有类型的代码库中。( ps: 这一段完全看不懂了)

总而言之,与 jQuery 剥离意味着我们可以更多地依赖 Web 标准,让 MDN Web 文档成为我们前端开发人员事实上的默认文档,在未来维护更具弹性的代码,并最终从我们打包好的程序中移除30kb的依赖,从而加快页面加载速度和 JavaScript 执行速度。

逐步解耦

虽然有一个目标在望,但是我们很清楚,用所有资源重写代码来替换 jQuery 是不可行的。如果冒然行动,如此匆忙的努力可能会导致网站功能出现许多倒退,然后很快将不得不淘汰这些倒退的功能。相反,我们采取循序渐进的方式:

  • 设置跟踪每行代码使用 jQuery 调用比率的指标,并监控该指标,以确保它保持不变或下降,而不是上升。
  • 我们不鼓励在任何新代码中导入 jQuery。为了方便自动化管理,我们创建了 eslint-plugin-jquery,如果有人尝试使用 jQuery 功能(例如 $.ajax),它将无法通过 CI 检查。
  • 现在旧代码中有很多违反 eslint 规则的行为,所有这些我们都在代码注释中使用特定的 eslint-disable 规则进行了注释。对于该代码的读者来说,这些注释将清楚地表明该代码并不代表我们当前的编码实践。
  • 我们创建了一个拉取请求机器人,当有人试图添加新的 eslint-disable 规则时,它会在拉取请求上留下评论并通知我们的团队。这样我们就可以尽早参与代码审查并提出替代方案。
  • 许多旧代码使用了 pjaxfacebox 这类 jQuery 插件,因此当我们使用 vanilla JS 替换它们时保持了它们的接口不变。静态类型检查帮助我们对这些重构更有信心。
  • 此处省略一段,实在看不懂,编都编不出来。。。
  • 我们维护了一个自定义构建的 jQuery 版本,当我们发现不再使用某个 jQuery 模块时,我们会将其从自定义版本中删除并发布一个更精简的版本。例如,在我们删除了 jQuery 的 CSS 伪选择器(如 :visible:checkbox)之后,我们就能够删除 Sizzle 模块;当最后一个 $.ajax调用被 fetch() 替换时,我们能够删除 AJAX模块。这样做有双重目的:加快 JavaScript 执行速度,同时确保新代码不能使用已删除的功能。
  • 根据我们的网站分析结果,我们会在可行的情况下尽快放弃对旧版本 Internet Explorer 版本的支持。每当某个 IE 版本的使用率低于某个阈值时,我们就会停止为其提供 JavaScript支持,并专注于测试和支持更现代的浏览器。早期放弃对 IE 8-9 的支持使我们能够使用许多浏览器新的功能,否则这些功能很难被通过打补丁的方式使用。
  • 作为我们在 GitHub.com 上构建前端功能的改进方法的一部分,我们专注于尽可能多地使用常规的HTML 代码,只在有必要时才添加 JavaScript 代码来作为一种渐进增强的方式。这样一来,那些使用 JS 增强的 Web 表单和其他 UI 元素通常也可以在浏览器禁用 JavaScript 的情况下工作。在某些情况下,我们能够完全删除某些遗留代码,而不必在 vanilla JS 中重写它们。

这几年来,通过以上所述和诸如此类的努力,我们逐渐减少了对 jQuery 的依赖,直到不再有一行代码引用它。

自定义标签

近年来引起轰动的一项技术是自定义标签,它是 Web Components 标准非常重要的一个特性,它使开发者能够将HTML页面的功能封装为 custom elements(自定义标签),这意味着用户无需下载、解析和编译额外的库或者框架代码。

自 2014 年以来,我们根据 Web Components v0 规范创建了一些自定义标签。但是,由于当时的标准仍在不断变化,我们没有投入太多精力。直到 2017 年 Web Components v1 规范发布并在 ChromeSafari 中实现,我们才开始更广泛地采用自定义标签。

在 jQuery 移除期间,我们寻找并提取出来那些适合通过自定义标签实现的对象。例如,我们将 facebox 中用来显示模态对话框的部分转换为 <details-dialog>

我们追求渐进式增强的理念也延伸到自定义标签上。这意味着我们在标签中尽可能的保留原内容,只在其基础之上做行为添加。例如,<local-time> 默认显示原始时间戳,被升级为将时间戳转换为本地时区的时间;当 <details-dialog>嵌套在 <details> 中时,即使没有 JavaScript 也具有交互功能,但通过可用性增强得到了升级。

以下是如何实现 <local-time> 自定义标签的示例:

代码语言:txt
复制
// The local-time element displays time in the user's current timezone
// and locale.
//
// Example:
//   <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 DOMShadow DOM 的强大特性有可能为 Web 解锁许多可能性,但这也使得为它打补丁变得更加困难。因为现在对它进行打补丁 会导致性能损失,即使对于操作与 Web 组件无关的 DOM 部分的代码也是如此,所以目前我们在生产环境中使用它是不可行的。

Polyfills (特指JavaScript中的补丁代码)

以下是帮助我们过渡到可以使用标准浏览器功能的补丁列表。我们仅在绝对必要时提供这些补丁,也就是说,它们只作为单独的 JavaScript 包提供给那些过时的浏览器使用以弥补兼容性的不足。

github/eventlistener-polyfill

github/fetch

github/form-data-entries

iamdustan/smoothscroll

javan/details-element-polyfill

jonathantneal/closest

kumarharsh/custom-event-polyfill

marvinhagemeister/request-idle-polyfill

mathiasbynens/Array.from

mathiasbynens/String.prototype.codePointAt

mathiasbynens/String.prototype.endsWith

mathiasbynens/String.prototype.startsWith

medikoo/es6-symbol

nicjansma/usertiming.js

rubennorte/es6-object-assign

stefanpenner/es6-promise

webcomponents/template

webcomponents/URL

webcomponents/webcomponentsjs

WebReflection/url-search-params

yola/classlist-polyfill

译文完!

结语:

本来就是件心血来潮的事,大周末的,寻思着两个小时也就弄完了,结果连看娃带吃饭,一天都没弄完,还是太天真。因为没能一鼓作气,难免半道泄气,期间多次强打精神总算翻译完了。

因为水平有限,再加上有些技术概念事先并不了解,有些地方还是比较难理解的,好在此篇并不着重讲具体技术,而是类似综述,于我本人而言,还是学到了一些方法论和“自以为新潮”的概念的,比如 Github 的工程师采用逐步解耦的方式慢慢与 jQuery 进行剥离的思想,放在其他软件开发领域也是有很强的指导性的,再比如新的 Web API 标准中支持自定义标签、Shadow DOM 这类之前都没有听过的概念等等。

至于译文中难免存在错误的或者纰漏,欢迎批评指正!

本来都打算发布了,结果在查一个概念的时候发现之前有人已经翻译过了,就取长补短了一下。

参考文章

GitHub:我们为什么会弃用jQuery?

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 从 GitHub.com 网站前端移除 jQuery
    • 为什么 jQuery 在早期有意义
      • 近些年的Web标准
        • 逐步解耦
          • 自定义标签
            • Polyfills (特指JavaScript中的补丁代码)
            • 结语:
            • 参考文章
            相关产品与服务
            机器翻译
            机器翻译(Tencent Machine Translation,TMT)结合了神经机器翻译和统计机器翻译的优点,从大规模双语语料库自动学习翻译知识,实现从源语言文本到目标语言文本的自动翻译,目前可支持十余种语言的互译。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档