JQuery has been completely removed from the front-end of GitHub.com
GitHub.com started using jQuery 1.2.1 in late 2007, a year before Google released Chrome. There was no standard way to query DOM elements through CSS selectors or to render their styles dynamically, and Internet Explorer’s XMLHttpRequest interface, like many other apis, suffered from inconsistencies between browsers.
JQuery makes DOM manipulation, creating animations, and “AJAX” requests fairly easy, basically enabling Web developers to create more modern, dynamic Web experiences. Best of all, the code you develop for one browser using jQuery works with other browsers. In GitHub’s early days, jQuery allowed small development teams to quickly prototype and develop new features without having to tailor code to each Web browser.
Extension libraries based on jQuery’s simple interface also form the foundation building blocks of the GitHub.com front end: Pjax (https://github.com/defunkt/jquery-pjax) and facebox (https://github.com/defunkt/facebox).
We will never forget such a useful base library created and maintained by John Resig and jQuery contributors.
Over the years, GitHub grew into a company with hundreds of engineers and gradually built a dedicated team responsible for the size and quality of the JavaScript code. We’ve been excluding technical debt, and sometimes technical debt grows with more and more dependencies that give us some value in the beginning, but those values also decline over time.
We can compare jQuery to the rapid evolution of Web standards supported by modern browsers:
-
The $(selector) mode can be replaced with querySelectorAll();
-
You can now switch CSS class names using element. classList;
-
CSS now supports defining visual animations in style sheets instead of JavaScript;
-
You can now use Fetch Standard to perform $.ajax requests;
-
The addEventListener() interface is stable enough to be used across platforms;
-
We can use lightweight libraries to encapsulate the event delegate pattern;
-
As the JavaScript language has evolved, some of the syntactic sugar provided by jQuery has become redundant.
Also, chained syntax doesn’t work the way we want to write code. Such as:
$('.js-widget')
.addClass('is-loading')
.show()
Copy the code
This syntax is simple to write, but by our standards it doesn’t convey our intent very well. Does the author expect one or more JS-Widget elements on the current page? Also, if we update the page tag and accidentally leave out the jS-Widget class name, will the browser throw an exception that tells us what’s wrong? By default, jQuery skips the entire expression when nothing matches the selector, but for us, this is a bug.
Finally, we started using Flow to annotate types so that static type checking could be performed at build time, and we found that chained syntax was not suitable for static analysis because almost all jQuery methods returned the same type. We chose Flow because features like the @Flow Weak pattern allowed us to gradually apply types to untyped codebase.
All in all, removing jQuery means we can rely more on Web standards, make MDN Web documentation the de facto default for front-end developers, maintain more resilient code in the future, and remove 30KB dependencies from our bundle, Speed up page loading and JavaScript execution.
While the end goal is set, we also know that it is not feasible to allocate all resources to remove jQuery at once. This rush could lead to a return of functionality. Instead, we adopted the following strategy:
1. Set metrics, track the rate at which the entire line of code calls jQuery, and monitor metrics over time to make sure it stays the same or goes down, not up.
2. We discourage the import of jQuery into any new code. For the convenience of automation, we created the eslint plugin – jquery (https://github.com/dgraham/eslint-plugin-jquery), if someone is trying to use jquery functions, such as $. Ajax, The CI check will fail.
3. There were a number of ESLint violations in the old code, which we annotated in code comments using the specific ESLint-Disable rule. Readers of this code should know that it does not conform to our current coding practices.
4. We created a pull request robot that will leave comments on pull requests when someone tries to add a new ESLint-Disable rule. This allows us to participate in code reviews early and suggest alternatives.
5. A lot of older code uses the PJAX and FaceBox plug-ins, so we internally re-implement their logic using JS while keeping their interfaces pretty much unchanged. Static type checking helps give us confidence in refactoring.
6. A lot of older code interacts with Rails-behavior, and our Ruby on Rails adapters are almost “unobtrusive” JS that attach AJAX lifecycle handlers to certain forms:
$(document).on('ajaxSuccess', 'form.js-widget', function(event, XHR, Settings, data) {// Insert response data into DOM})
Copy the code
7. We chose to trigger fake Ajax * lifecycle events and keep these forms submitting asynchronously as before, rather than overriding all calls at once, just using fetch() internally.
8. We maintain a version of jQuery ourselves, and whenever we find that we no longer need a module of jQuery, we remove it from the custom version and release a lighter version. For example, after removing jQuery’s CSS pseudo-selectors (e.g. : Visible or :checkbox) we can remove the Sizzle module, which can be removed when all $.ajax calls are replaced by fetch().
This serves two purposes: to speed up JavaScript execution and to ensure that no new code tries to use the removed functionality.
9. We will withdraw support for older versions of Internet Explorer as soon as possible based on the analysis results of the site. Whenever a version of IE falls below a certain threshold, we stop providing JavaScript support and focus on supporting more modern browsers. Moving away from IE 8 and IE 9 support early meant that we could adopt a lot of native browser features that would otherwise have been difficult to polyfill.
10. As part of our new approach to developing front-end features for GitHub.com, we focused on using regular HTML as much as possible, and gradually added JavaScript behavior as incremental enhancements. As a result, Web forms and other UI elements that are enhanced with JS usually work well on browsers with JavaScript disabled. In some cases, we can remove some legacy code completely without having to rewrite it using JS.
Over the years, we have gradually reduced our reliance on jQuery until not a single line of code references it.
There has been a lot of hype in recent years about a new technology called custom elements — a browser-native component library that means users don’t have to download, parse, and compile extra bytes.
Since 2014, we have created some custom elements based on the V0 specification. However, because standards are still changing, we don’t put much effort into it. It wasn’t until 2017, when the Web Components V1 specification was released and Chrome and Safari implemented it, that we started to adopt custom elements more widely.
While removing jQuery, we are also looking for a schema to extract custom elements. For example, we will be used to display the modal dialog box facebox converted to < the details – dialog > element (https://github.com/github/details-dialog-element).
Our philosophy of progressive enhancement extends to custom elements as well. This means we will keep as much of the tag content as possible and then add behavior to the tag. For example, <local-time> defaults to showing raw timestamps, which have been upgraded to convert time to local time zones, while <details-dialog>, when embedded in the < Details > element, can be interactive without JavaScript, It has been upgraded to include auxiliary enhancements.
Here is an example of implementing a <local-time> custom element:
// local-time Displays the time based on the user's current time zone. // // For 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) }
Copy the code
We are looking forward to the Shadow DOM for Web components. The power of Shadow DOM opens up a lot of possibilities for the Web, but it also makes polyfill more difficult. Because polyfills lead to performance losses, they are not feasible to use in a production environment.
https://githubengineering.com/removing-jquery-from-github-frontend/
ArchSummit global Architect Summit will be held in Beijing International Convention Center on December 7-8, focusing on topics such as micro-service financial architecture, micro-service architecture, data infrastructure platform construction, short video architecture, blockchain, information privacy security and so on. Technical experts from Alibaba, Netflix, Baidu, LinkedIn and others were invited to share.
30% discount registration, immediate reduction of 2040 yuan, any questions welcome to consult Lachel- Ash, ticketing manager, tel/wechat: 17326843116.