为什么全球最大同性交友平台Github放弃jquery?

2018-10-28

Jessie Chen

 

7月17日,GitHub改版并放弃了jQuery, 这对于GiHub来说,绝对是一件可以载入公司史册的大事

 

七月,『全球最大同性交友平台』GitHub 被微软以 75 亿美元(折合人民币 480 亿)的价格正式收购,这一事件引发诸多程序员担忧:

微软收购之后,Github 是否会将不再开源?
为防范于未然,开发者正把 repos 迁移到 GitLab 等其他 Git 托管平台;
GitHub 有 Atom,微软有 Visual Studio,用户明显重复。

对此,微软回应了一切,并表示不打算在 GitHub 上做太多改变,且以开发者为中心的初心不会改变,会积极地拥抱开源。

如今,Github 也做出一些微软特色的改变。

 

为什么最初需要jQuery

 

我们最近刚刚完成了一个里程碑,成功地从GitHub.com的前端代码的依赖中去掉了jQuery。这标志着这项一点一滴持续了多年的jQuery解耦合工作的完成,以及我们终于可以完全删除这个库了。

GitHub.com在2007年末引入了jQuery 1.2.1作为依赖。当时距离Google发布Chrome浏览器的第一版,还有一年的时间。

当时没有什么标准的方法,通过CSS选择器,来查询DOM元素,也没有标准的方式,来实现元素的视觉动画,而由Internet Explorer倡导的XMLHttpRequest接口,也像许多其他API一样,在各种浏览器上的实现不一致。

而jQuery使得操作DOM、定义动画和实现“AJAX”请求,变得十分简单。简单来说,它使得Web开发者可以创建更现代、更动态的效果。

最重要的是,通过jQuery在一种浏览器上实现的功能,基本上也能在其他浏览器上运行。

在GitHub的早期,许多功能才刚刚起步,有了jQuery,我们的小团队才能迅速地建立原型、并推出新功能,而不需要为每种Web浏览器调整代码。

我们还把jQuery简单的接口,作为蓝图来构建扩展库,这些库(pjax, https://github.com/defunkt/jquery-pjax和Facebox,https://github.com/defunkt/facebox),后来成了GitHub.com前端的其他部分的组成部分。

我们会永远感谢John Resig和其他jQuery贡献者们,创建并维护了这个十分有用、并且在历史上十分重要的库。

 

后来的Web标准

 

多年以后,GitHub成长为拥有数百名工程师的公司,还逐渐组成了一个独立的团队,专门负责我们发送到浏览器上的JavaScript代码的尺寸和质量。

我们一直在监视技术债务,而有些技术债务的原因,是那些曾经有价值、但后来随着时间的发展而失去了价值的依赖。

而对于jQuery,我们将它与现代浏览器中迅速发展的Web标准做了比较,结果发现:

  • $(selector) 可以简单地用querySelectorAll()替换;

  • CSS类名切换,可以通过Element.classList实现;

  • CSS现在支持在样式表中定义视觉动画,无需使用JavaScript;

  • $.ajax请求可以用Fetch标准实现;

  • addEventListener()接口已经十分稳定,足以跨平台使用;

  • 我们可以用一个轻量级的库,来封装事件代理模式;

  • jQuery提供的一些语法糖,已随着JavaScript语言的发展,而变得多余。

而且,链式语法并不能满足我们直观地书写代码的需要。例如:

$('.js-widget')
  .addClass('is-loading')
  .show()

这种语法很容易编写,但以我们的标准来看,它并不能很好地传达作者的意图。作者希望页面上只有一个JS-Widget元素、还是有多个?

而且,如果我们修改网页代码时,一不小心删掉了JS-Widget类名,浏览器会产生异常并告诉我们发生了错误吗?

默认情况下,如果类名不匹配,jQuery会静默地忽略整个表达式,但在我们看来,这种行为与其说是功能,不如说是个Bug。

最后一点,我们想使用Flow(https://flow.org/)进行标注,从而在构建时实现静态类型检查。

但我们得出结论,链式语法并不能很好地适应静态分析,因为几乎所有jQuery的函数的返回值,都是同一种类型。

我们选择Flow、而不是其他库的原因是因为当时像@flow weak模式等特性可以让我们逐渐地、有效地给大量几乎没有任何类型的代码添加类型。

总的来说,jQuery解耦合,意味着我们可以更依赖于Web标准,将MDN Web文档,作为事实上的前端开发标准,方便以后维持代码的灵活性,并最终从打包文件中,去掉一个30KB的依赖,提高页面加载速度、和JavaScript的执行时间。

 

增量解耦合

即使确定了最终目标,我们也不能简单地,把所有资源都花在,使用原生JS重写jQuery的事情上。

一旦发生什么事情,这种急功近利,会导致许多网站功能倒退,从而不得不花更多时间去解决。我们必须要这样做:

设定好度量标准,跟踪jQuery调用次数和全部代码行数的比例,并随时监视该度量,保证它不变或减小,而不会增加。

我们不鼓励在任何新代码中使用jQuery。为了使用自动化减轻工作量,我们创建了eslint-plugin-jquery(https://github.com/dgraham/eslint-plugin-jquery#readme),如果任何人尝使用jQuery功能(如$.ajax),它就会造成CI检查失败。

旧代码中有大量的ESLint规则违反,这些违反我们都使用eslint-disable规则在代码注释中标注出来了。这样就能尽快进行代码审查、并集思广益。

许多旧代码显式地耦合了Pjax和Facebox这两个jQuery插件的外部接口,因此我们在使用原生JS,替换这两者的实现时,尽力保持接口不变。静态检查让我们能更信心地进行重构。

许多就代码都与rails-behaviors(http://josh.github.io/rails-behaviors/)有接口,后者是我们在Ruby on Rails和JS之间的适配器。这种接口会为特定的表单,添加一个AJAX生命周期处理函数。

  // LEGACY APPROACH
  $(document).on('ajaxSuccess''form.js-widget'function(event, xhr, settings, data{
    // insert response data somewhere into the DOM
  })

为避免不得不用新方法,一次性重写整个网站,我们采用了触发伪“*AJAX*”生命周期事件的方式,使这些表单,能像以前一样继续异步提交内容,只不过内部使用的是fetch()。

我们定制了一个jQuery,一旦我们认为某个模块不再需要,就把它从定制版本中删掉,使jQuery更灵巧。

例如,在删除最后一个jQuery专用的CSS伪类(:visible、:CheckBox等),我们就删掉了Sizzle模块(https://sizzlejs.com/);在使用fetch()替换了最后一个$.ajax调用之后,就删掉了AJAX模块。

这样做有两个目的,一是加快JavaScript执行速度,一是确保新功能不会使用被删掉的功能。

根据网站访问分析的结果,只要有可能,我们就会删掉支持旧Internet Explorer版本的部分。当某个IE版本的使用率,降到某个阈值之下,我们就不会再为其提供JavaScript,从而得以专注于,支持更多现代浏览器。

提早去掉IE8~9的支持,使得我们可以使用更多的原生浏览器功能,不用再勉强进行Polyfill。

作为构建GitHub.com前端的新方法的一部分,我们尽可能采用基础的HTML来实现功能,只把JavaScript用作渐进式增强。

这样,即使Web表单和其他UI元素上使用了JS,它们也能在禁用了JavaScript的浏览器中运行。一些情况下,我们可以删掉整个旧有行为,不用再使用原生JS重写。

通过这些方法(以及多年来积累的其他方法),我们得以逐渐地减小对jQuery的依赖,直到没有一行代码使用它。

 

自定义元素

近几年人们谈论得最多的一项技术就是自定义元素,它是个浏览器原生的组件库,也就是说用户无需下载、解析或编译任何框架。

我们从2014年起,就根据v0规格,建立了一些自定义元素。但是,由于当时的Web标准依然不明确,所以我们并没有深入研究。

直到2017年,Web组件的v1规格发布,而且Chrome和Safari都开始支持,我们才开始在大范围内使用自定义元素。

在jQuery迁移过程中,我们寻找适合提取成自定义元素的部分。例如,我们将使用Facebox显示对话框的代码,改成了<Details-Dialog>元素。

渐进式增强的思想,也应用到了自定义元素中。就是说,我们尽可能保持标签的内容,仅在标签不能实现的地方,添加新的行为。

例如,<local-time>默认会显示原始的时间戳,然后增强翻译成本地时区内的时间;而<details-dialog>如果嵌入到<details>元素中,那么即使没有JavaScript,本身也是交互式的,但会利用提高可用性的功能进行增强。

下面是实现自定义元素<local-time>的例子。

 // 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 DOM。

Shadow DOM的强大功能,可以给Web带来许多可能性,但也使得它很难polyfill。

因为现在的polyfill方式,会给那些操纵与Web组件无关的DOM的代码,也造成大量性能损失,所以还不适合在生产环境中使用。

 

Polyfill

我们在转换成标准浏览器功能的过程中,使用了下面这些polyfill。我们尽量仅在绝对必须时——即需要兼容旧版本浏览器时——才使用polyfill。

  • 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。

原文:https://githubengineering.com/removing-jquery-from-github-frontend/

 

近期开课hot
logo

Follow Us

linkedinfacebooktwitterinstagramweiboyoutubebilibilitiktokxigua

We Accept

/image/layout/pay-paypal.png/image/layout/pay-visa.png/image/layout/pay-master-card.png/image/layout/pay-stripe.png/image/layout/pay-alipay.png

地址

Level 10b, 144 Edward Street, Brisbane CBD(Headquarter)
Level 8, 11 York st, Wynyard, Sydney CBD
Business Hub, 155 Waymouth St, Adelaide SA 5000

Disclaimer

footer-disclaimerfooter-disclaimer

JR Academy acknowledges Traditional Owners of Country throughout Australia and recognises the continuing connection to lands, waters and communities. We pay our respect to Aboriginal and Torres Strait Islander cultures; and to Elders past and present. Aboriginal and Torres Strait Islander peoples should be aware that this website may contain images or names of people who have since passed away.

匠人学院网站上的所有内容,包括课程材料、徽标和匠人学院网站上提供的信息,均受澳大利亚政府知识产权法的保护。严禁未经授权使用、销售、分发、复制或修改。违规行为可能会导致法律诉讼。通过访问我们的网站,您同意尊重我们的知识产权。 JR Academy Pty Ltd 保留所有权利,包括专利、商标和版权。任何侵权行为都将受到法律追究。查看用户协议

© 2017-2024 JR Academy Pty Ltd. All rights reserved.

ABN 26621887572