前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Github 移除 JQuery 的过程

Github 移除 JQuery 的过程

作者头像
用户7293182
发布2022-01-20 18:07:38
2K0
发布2022-01-20 18:07:38
举报
文章被收录于专栏:jQuery每日经典jQuery每日经典

本文翻译自Removing jQuery from GitHub.com frontend https://github.blog/2018-09-06-removing-jquery-from-github-frontend/

我们最近完成了一个里程碑,我们可以将jQuery作为GitHub.com前端代码的依赖项删除。这标志着一个渐进的、长达数年的、与jQuery越来越脱钩的过渡的结束,直到我们能够完全删除这个库。在这篇文章中,我们将解释一点我们最初是如何开始依赖jQuery的,我们是如何意识到不再需要jQuery的,并指出我们没有用另一个库或框架替换它,而是能够使用标准的浏览器api实现所需的一切。

为什么jQuery在早期就有意义

GitHub.com在2007年底引入jQuery 1.2.1作为依赖项。从某种意义上讲,那是谷歌发布其Chrome浏览器第一个版本的前一年。没有通过CSS选择器查询DOM元素的标准方法,也没有对元素的视觉样式进行动画处理的标准方法,而由Internet Explorer开创的XMLHttpRequest接口与许多其他api一样,在浏览器之间是不一致的。

jQuery使操作DOM、定义动画和发出“AJAX”请求变得简单——基本上,它使web开发人员能够创建更现代、更动态的体验,而这些都是其他人无法比拟的。最重要的是,使用jQuery在一个浏览器中构建的JavaScript特性通常也可以在其他浏览器中工作。在GitHub的早期,当它的大部分功能仍然得到充实时,这使得小型开发团队能够快速地进行原型化,并获得新的功能,而不必专门为每个web浏览器调整代码。

jQuery的简单接口还用作设计扩展库的蓝图,这些扩展库稍后将用作GitHub.com前端的其余部分:pjax和facebox的构建块。

我们将永远感谢John Resig和jQuery贡献者创建和维护了这样一个有用的、并且在目前是必要的库。

未来几年的Web标准

多年来,GitHub成长为一家拥有数百名工程师的公司,并逐渐组建了一个专门的团队,负责为web浏览器服务的JavaScript代码的大小和质量。我们一直在关注的一件事是技术债务,有时技术债务围绕着曾经提供了价值,但随着时间推移其价值下降的依赖关系而增长。

在jQuery方面,我们将其与现代浏览器中支持的web标准的快速发展进行了比较,发现:

  • $(selector)模式可以很容易地替换为querySelectorAll();
  • 现在可以使用Element.classList实现CSS类名切换;
  • CSS现在支持在样式表而不是JavaScript中定义可视化动画;
  • $.ajax请求可以使用Fetch标准执行;
  • addEventListener()接口足够稳定,可以跨平台使用;
  • 我们可以很容易地用轻量级库封装事件委托模式;
  • 随着JavaScript语言的发展,jQuery提供的一些语法糖已经变得多余了。

此外,链接语法也能满足我们编写代码的需要。例如:

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

这种语法编写起来很简单,但按照我们的标准,并不能很好地传达意图。作者希望在这个页面上有一个或多个js小部件元素吗?另外,如果我们更新了页面标记,并且意外地漏掉了js小部件的类名,浏览器中的异常是否会通知我们出了问题?默认情况下,当没有匹配初始选择器时,jQuery会自动跳过整个expresion;但对我们来说,这种行为是一个bug,而不是一个特性。

最后,我们想开始用Flow对类型进行注释,以便在构建时执行静态类型检查,我们的结论是,链接语法不适合进行静态分析,因为jQuery方法调用的几乎每个结果都是同一类型的。我们之所以选择Flow而不是alternatives,是因为当时@Flow弱模式等特性允许我们逐步高效地开始将类型应用到基本上没有类型的代码基。

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

增量解耦

即使有了最终目标,我们知道仅仅分配所有资源是不可行的,我们必须重写从jQuery到vanilla JS的所有内容。如果有的话,这样仓促的努力很可能会导致网站功能的许多倒退,我们以后将不得不剔除。相反,我们:

设置指标,跟踪每行代码使用jQuery调用的比率,并随时间监视该图,以确保它要么保持不变,要么下降,而不是上升。

我们不鼓励在任何新代码中导入jQuery。为了方便使用自动化,我们创建了eslint插件jquery,如果有人试图使用jquery特性(例如$.ajax),它将使CI检查失败。

现在旧代码中有很多违反eslint规则的行为,我们都在代码注释中用特定的eslint禁用规则进行了注释。对于该代码的读者来说,这些注释将作为一个明确的信号,表明该代码并不代表我们当前的编码实践。

我们创建了一个pull请求bot,每当有人试图添加一个新的eslint禁用规则时,它都会在我们的团队中对pull请求ping留下评论。这样我们就可以尽早参与代码评审并提出备选方案。

许多旧代码都与pjax和facebox jQuery插件的外部接口有显式耦合,因此我们保持了它们的接口相对相同,而在内部使用vanilla JS替换了它们的实现。静态类型检查有助于我们对这些重构有更大的信心。

大量与rails行为接口的旧代码,我们的Ruby on rails适配器采用“不引人注目”的JS方式,将AJAX生命周期处理程序附加到某些表单:

我们不必一次将所有这些调用站点重写为新方法,而是选择触发假ajax*生命周期事件,并让这些表单像以前一样异步提交其内容;只有这次fetch()在内部使用。

我们维护了一个jQuery的定制版本,当我们发现不再使用jQuery的某个模块时,我们会将其从定制版本中删除并发布一个更精简的版本。例如,在我们删除了特定于jQuery的CSS伪选择器(如:visible或:checkbox)的最终用法之后,我们能够删除Sizzle模块;当最后一个$.ajax调用被fetch()替换时,我们能够删除ajax模块。这有双重目的:加快JavaScript的执行速度,同时确保不会创建新的代码来尝试使用删除的功能。

根据我们的网站分析,一旦可行,我们就不断放弃对旧版Internet Explorer的支持。每当某个IE版本的使用低于某个阈值时,我们就会停止向它提供JavaScript,并专注于测试和支持更现代的浏览器。早期放弃对IE8-9的支持使我们能够采用许多本机浏览器特性,否则这些特性将很难填充。

作为我们在GithUB.com上构建前端功能的一种改进方法的一部分,我们专注于尽可能多地使用常规HTML基础,只添加JavaScript行为作为渐进增强。因此,即使那些使用JS增强的web表单和其他UI元素通常也会在浏览器中禁用JavaScript。在某些情况下,我们能够完全删除某些遗留行为,而不必在vanilla JS中重写它们。

经过这些年和类似的努力,我们逐渐减少了对jQuery的依赖,直到不再有一行代码引用它。

自定义元素

近年来掀起了一股热潮的一项技术是自定义元素:浏览器自带的组件库,这意味着没有额外的字节供用户下载、解析和编译框架。

自2014年以来,我们已经基于v0规范创建了一些自定义元素。然而,由于当时的标准仍在不断变化,我们没有投入那么多。直到2017年Chrome和Safari都发布并实现了Web组件v1规范,我们才开始更广泛地采用定制元素。

在jQuery迁移期间,我们寻找适合作为自定义元素提取的模式。例如,我们将显示模式对话框的facebox用法转换为

元素。

我们追求进步的总体理念也延伸到了定制元素。这意味着我们将尽可能多的内容保存在标记中,并且只在标记上添加行为。例如,默认显示原始时间戳,并升级以将时间转换为本地时区,而

嵌套在元素中时,即使没有JavaScript也具有交互作用,但通过辅助功能增强进行升级。

下面是如何实现自定义元素的示例:

代码语言:javascript
复制
// The local-time element displays time in the user's current timezone
// and locale.
//
// Example:
//   Sep 6, 2018
//
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组件的一个方面是影子DOM。Shadow DOM的强大特性有可能为web打开许多可能性,但这也使得它更难填充。因为polyfilling现在会导致性能损失,即使是处理与web组件无关的DOM部分的代码,我们也不可能开始在生产中使用它。

Polyfills

这些Polyfills 帮助我们过渡到使用标准浏览器功能。我们只在绝对必要时才尝试提供这些polyfill,即作为单独的“兼容性”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
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 jQuery每日经典 微信公众号,前往查看

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

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 为什么jQuery在早期就有意义
  • 未来几年的Web标准
  • 增量解耦
  • 自定义元素
  • Polyfills
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档