最近,我们从GitHub.com的前端代码中彻底移除了jQuery,这标志着我们多年来逐步移除jQuery的工作告一段落,这对我们来说是一个里程碑事件。这篇文章将描述我们过去是如何依赖jQuery的,随着时间的推移,我们意识到不再需要它,但最终,我们没有用另一个库或框架替换它,而是使用标准的浏览器API实现了我们需要的一切。早期,jQuery对我们意义重大GitHub.com于2007年底开始使用jQuery1.2.1,比Google发布Chrome早一年。没有通过CSS选择器查询DOM元素的标准方法,也没有动态呈现元素样式的标准方法,并且InternetExplorer的XMLHttpRequest接口与许多其他API一样,在浏览器之间存在不一致。jQuery使DOM操作、创建动画和“AJAX”请求相当容易,基本上,它使Web开发人员能够创建更现代和动态的Web体验。最棒的是,使用jQuery为一种浏览器开发的代码也适用于其他浏览器。在GitHub的早期,jQuery使小型开发团队能够快速制作原型并开发新功能,而无需专门为每个Web浏览器调整代码。构建在jQuery简单界面之上的扩展库也成为GitHub.com前端的基本构建块:pjax和facebox。我们永远不会忘记由JohnResig和jQuery贡献者创建和维护的这样一个有用的基础库。后来的Web标准多年来,GitHub成长为一家拥有数百名工程师的公司,并逐渐建立了一支专门负责JavaScript代码规模和质量的团队。我们一直在排除技术债务,有时技术债务会随着依赖关系的增长而增长,这些依赖关系起初会给我们带来一些价值,但随着时间的推移,这种价值也会降低。我们可以将jQuery比作现代浏览器支持的Web标准的快速发展:$(selector)模式可以替换为querySelectorAll();现在可以使用Element.classList实现CSS类名切换;CSS现在支持在JavaScript中定义可视化动画;FetchStandard现在可用于执行$.ajax请求;addEventListener()接口足够稳定,可以跨平台使用;我们可以使用轻量级库来封装事件委托模式;随着JavaScript语言的发展,jQuery提供的一些语法糖变得多余了。此外,链式语法不满足我们编写代码的方式。例如:$('.js-widget').addClass('is-loading').show()这种语法写起来很简单,但按照我们的标准,它并不能很好地表达我们的意图。作者是否期望当前页面上有一个或多个js-widget元素?另外,如果我们更新页面标记并且不小心遗漏了js-widget类名,浏览器会抛出异常来告诉我们哪里出了问题吗?默认情况下,jQuery会在没有匹配选择器的情况下跳过整个表达式,但对我们来说,这是一个错误。***,我们开始使用Flow注释类型在构建时执行静态类型检查,我们发现链接语法不适合静态分析,因为几乎所有jQuery方法都返回相同类型的结果。我们当时选择了Flow,因为像@flow弱模式这样的特性允许我们逐渐将类型应用到无类型的代码库中。总而言之,删除jQuery意味着我们可以更多地依赖Web标准,使MDNweb文档成为前端开发人员事实上的默认设置,在未来维护更具弹性的代码,并将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交互,我们的RubyonRails适配器几乎是“不显眼”的JS,它将AJAX生命周期处理程序附加到某些表单://oldmethod$(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.根据站点的分析,我们将尽快停止对旧版本InternetExplorer的支持。每当IE版本的使用率低于某个阈值时,我们就会停止为其提供JavaScript支持,并专注于支持更多现代浏览器。尽早放弃对IE8和IE9的支持意味着我们可以采用许多本机浏览器功能,否则这些功能将难以填充。10.作为GitHub.com前端功能开发新方法的一部分,我们专注于尽可能多地使用常规HTML,并逐渐添加JavaScript行为作为渐进增强。因此,使用JS增强的Web表单和其他UI元素通常可以在禁用JavaScript的浏览器上运行。在某些情况下,我们可以完全去除一些遗留代码,而无需用JS重写。多年来,我们逐渐减少了对jQuery的依赖,直到没有一行代码引用它。CustomElements近年来被大肆宣传的一项新技术是CustomElements——一种浏览器原生的组件库,这意味着用户无需额外的字节来下载、解析和编译。自2014年以来,我们根据v0规范创建了一些自定义元素。然而,由于标准仍在不断变化,我们还没有投入太多精力。直到2017年,WebComponentsv1规范发布,Chrome和Safari实现了它,我们才开始更广泛地采用自定义元素。在删除jQuery期间,我们也在寻找用于提取自定义元素的模式。例如,我们将用于显示模态对话框的facebox转换为
