译者 | GitHub 后端工程建设项目组 翻译者 | 邪见 撰稿 | 覃云 – 后端之巅 前段时间,他们将 jQuery 全然从 GitHub.com 的后端标识符中去除了,这标志着他们数月来逐步移除 jQuery 这个渐进的过程终于结束了,这对他们来说是两件划时代的该事件。这首诗将介绍过去他们是如何倚赖上 jQuery 的,随著天数地流逝,他们意识到不再须要它,但到最后他们并没采用另两个库或架构替代它,而是采用国际标准的应用程序 API 实现了他们所须要的一切。晚期,jQuery 对他们意义重大
GitHub.com 在 2007 月底已经开始采用 jQuery 1.2.1,那是Google发布 Chrome 应用程序的前一年。当时还没通过 CSS 示例来查阅 DOM 原素的国际标准方式,也没静态图形原素的式样的国际标准方式,而 Internet Explorer 的 XMLHttpRequest USB与其它很多 API 一样,在应用程序之间存在见下文难题。
jQuery 让 DOM 操作、建立动画电影和“AJAX”允诺显得十分单纯,大体上,它让 Web 合作开发者能建立更加现代的静态 Web 新体验。最重要的是,采用 jQuery 为两个应用程序合作开发的标识符也适用于于其它应用程序。在 GitHub 的晚期阶段,jQuery 让较大型的合作开发项目组能加速展开蓝本设计并合作开发上新功能,而无须专门特别针对特别针对每一 Web 浏览器调整标识符。
如前所述 jQuery 单纯的USB所构筑的扩充库也成为 GitHub.com 后端的基础构筑块:pjax(https://github.com/defunkt/jquery-pjax)和 facebox(https://github.com/defunkt/facebox)。
他们将总有一天不会忘掉 John Resig 和 jQuery COBOL建立和保护的这样两个管用的基本库。
后来的 Web 国际标准多年来,GitHub 高速成长为一家拥有数千名技师的公司,并逐渐成立了两个专门特别针对的项目组,负责管理 JavaScript 标识符的规模和产品质量。他们一直在须建控制技术负债,有时候控制技术负债会随著倚赖项的激增而增长,那些倚赖项在一已经开始会为他们带来一定的商业价值,但那些商业价值也随著天数的流逝而下降。
他们能将 jQuery 与现代应用程序支持的 Web 国际标准的加速进化展开比较:
$(selector) 商业模式能采用 querySelectorAll() 来代替;
现在能采用 Element.classList 来实现 CSS 类名切换;
CSS 现在支持在式样表中而不是在 JavaScript 中定义可视动画电影;
现在能采用 Fetch Standard 执行 $.ajax 允诺;
addEventListener() USB已经足够稳定,能跨平台采用;
他们能采用轻量级的库来封装该事件委托商业模式;
随著 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 插件,所以他们在保持它们的USB几乎不变的同时,在内部采用 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 = LocalTimeElement window.customElements.define(local-time, LocalTimeElement) }他们很期待 Web 组件的 Shadow DOM。Shadow DOM 的强大功能为 Web 带来了很多可能性,但也让 polyfill 显得更加困难。因为采用 polyfill 会导致性能损失,因此在生产环境中采用它们是不可行的。
英文原文
https://githubengineering.com/removing-jquery-from-github-frontend/