13

How I Learned to Stop AngularJS and Love the Angular

 4 years ago
source link: https://bytes.grubhub.com/how-i-learned-to-stop-angularjs-and-love-the-angular-e84b0aabb49d
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

How I Learned to Stop AngularJS and Love the Angular

Image for post
Image for post

Quick, who plays the Hulk in the Marvel Cinematic Universe? If you said Mark Ruffalo, you’re mostly right — Ed Norton debuted the not-so-jolly green giant in 2008’s Incredible Hulk but Ruffalo has been transforming into the big green machine since 2012’s The Avengers.

You may also remember that Marvel Studios’ recasting announcement in 2010 really upset the fanboys. They went gamma at the thought of the Oscar-nominated Norton being replaced by a then little-known scruffy looking indie actor.

However, Ruffalo’s dry, sardonic portrayal of the viridescent behemoth and his more fragile alter ego, Dr. Bruce Banner, won over the skeptics. And after three more Hulk appearances, most fans couldn’t imagine a better actor to put on the tattered Hulk pants. Changing actors in mid-stride is never easy, but Hollywood filmmakers have shown that with the right replacement, you can silence the haters and win at the box office.

Which brings us to the recasting dilemma here at Grubhub: the replacement of AngularJS by (it’s just) Angular.

The story so far…

In 2013, we chose AngularJS as our go-to web application framework because we believed it was the best available tool at the time. It had all the goodies: dependency injection, a clear architectural pattern, and two-way data binding (it was cool at the time). And we weren’t the only ones — by 2014, AngularJS was the most popular single-page application framework out there (as measured by GitHub interest).

Image for post
Image for post
“Do you even trend?”

A new challenger enters the ring

About one year later (or 73 in JavaScript years), Facebook came along and shook things up in JS-land. In 2015, they open sourced their ReactJS framework, which had a lot in it, like a sensible one-way data flow paradigm, easy-to-follow architecture, and a super fast rendering engine. Its eye-opening efficacy forced everyone to second guess who they brought to the party — including perhaps the AngularJS core team.

People were rightfully seduced by React. It brought a slew of great ideas to the table, some of which fixed some of AngularJS’s inherent wrongs. Slow page rendering? VDOM FTW! Lack of predictability? One-way data mic drop.

Before we proceed, here’s a quick explanation of some single-page application (SPA) conventions. SPAs are essentially giant JavaScript applications that run in the browser. Not long ago, most developers’ understanding of browser JavaScript was fancy menus and annoying pop-up scripts. Now imagine a pop-up script that went through the Christian Bale character training regimen. What you end up with is a very powerful (if not bloated) set of tools that let developers do a lot more than create pretty menus that link to other parts of the site. Developers can effectively build the entire site — all in JavaScript.

Older SPA frameworks (a la AngularJS, EmberJS, KnockoutJS) take an HTML document and, using JavaScript, make changes to its elements directly. Think of it like that show on HGTV where they take a house and rearrange its furniture. It’s still the same house, just… better.

Newer frameworks like ReactJS are kind of like that other show on HGTV where instead of redecorating the old house, they build a brand-new one on top of it. Instead of changing the HTML document, ReactJS uses something called the Virtual Document Object Model (VDOM), a sort of super clone of the actual HTML Document Object Model that’s easier to manipulate. It’s like the page is jacked into the Matrix and the developer is Neo.

Image for post
Image for post
“There is no HTML”

The other fundamental difference in ReactJS’s approach is the one-way data paradigm. In a nutshell, ReactJS makes sure data from the backend only goes through a single unmitigated route before being presented to the application’s user. In other words, from the moment it’s requested to the moment it’s displayed, retrieved data remains constant.

AngularJS and other frameworks like it emphasize the Model View Controller (MVC) or Model View ViewModel (MVVM) pattern. The key part of this pattern, the model, is passed around the application and can have all sorts of things happen to it, even at the display level (i.e. two-way data binding).

In addition to the hygienic concerns, passing around a model with impunity makes debugging more difficult and harder to reason about what an application is actually doing during an operation; no developer wants to play “who moved my cheese” with data integrity issues. Knowing that data only flows in one direction and through a controlled chain of custody can make application development significantly saner.

Image for post
Image for post

Coming soon: Angular 2 — The Sequel

As mentioned before, it wasn’t just the developers impressed with ReactJS’s approach. The AngularJS core team adjusted their framework’s trajectory to counter ReactJS and tackle some of AngularJS’s intrinsic issues. In 2014 (yes, all in the same year), the AngularJS team announced their plans for what was then dubbed Angular 2 and introduced a twist that would have made M. Night Shyamalan blush.

The AngularJS core team changed almost everything. Like pressing a giant reset button, the core team completely reimagined the framework from the ground up. And despite the fact that several critical issues from the previous version were addressed, there was no clear upgrade path from AngularJS to Angular 2 that didn’t involve substantial amounts of refactoring and rewriting. Angular 2 was, for all intents and purposes, a completely different framework and, while new applications would be able to immediately leverage its benefits, existing AngularJS applications would sadly stare in from the sidelines.

Despite efforts to assure the community that there would be a clear migration path, most were not happy about the directional shift. Not because Angular 2 wasn’t going to be a better framework (it is), but a direct upgrade seemed next to impossible.

The developer community fractured after the announcement. Some rage quit and declared they would be switching to ReactJS. Some even started their own competing framework (see AureliaJS). And of course, some pre-ordered the game and devoted themselves to Angular 2 (which is now called just Angular, having dropped the 2 in favor of a semantic versioning scheme).

Meanwhile, back at Avengers Tower…

At Grubhub, our engineers’ consternation mirrored the developer community. And while some teams eventually replaced their AngularJS projects with React, the consumer web team, which I lead, wasn’t ready to make the switch to Angular 2 (or even React for that matter). While we did have our reservations, our primary concern was around the perceived effort of an “upgrade” — any rewrite project would be extremely disruptive to the business from a time and cost perspective.

But at the end of the day, we still had an application to maintain. And we had an obligation to the business and, more importantly, to our customers, ensuring we gave them the best experience possible. So while we had our eyes set on an “eventual” migration to Angular 2, we did everything we could to improve the existing application.

We tried smoothing over any AngularJS rough spots by leveraging every trick we could muster. We combatted slow rendering by replacing the default AngularJS templating process with a library called HyperScript — a Virtual DOM library similar to the one in ReactJS. This allowed pages to load faster and improved our perceived load times drastically, especially on those pages with a lot of elements.

We went through our app with a fine-toothed comb and removed as much two-way binding as possible to manage the infamous AngularJS digest loop issues. As mentioned before, two-way binding seemed really cool at the time — like mullets, acid-washed jeans, or LED lights on the undercarriage of a 2005 Honda Accord. But the ugly truth of out-of-control change detection quickly knocks sense into all but the densest developer. By eliminating as much two-way binding as we could, we not only dramatically improved the site’s responsiveness, we slept better at night knowing our application wasn’t the software equivalent of an 80’s fashion rerun gone wrong.

Image for post
Image for post
“Friends don’t let friends wear high waisted jeans”

For almost two years (or 73 in JavaScript years), we did our best to extract every ounce of performance we could out of our AngularJS app. And as a result, the application’s business metrics (conversion, bounce rate, et al.) were solid and met or exceeded expectations. However, as time passed, the reality of working in a framework on borrowed time and with an incipient end-of-life announcement started setting in. We needed to plan our next move or else be stuck with something that had little or no community support and that no one would want to work with.

And as Angular 2 officially premiered in 2016, and subsequent iterations later (as of this article’s publication, Angular is at version 5), our team genuinely liked the way it turned out. Stuff like server-side rendering out of the box, embracing TypeScript, and intrinsic performance improvements are actually really neat and could potentially add a lot more spice to our application.

Marvel decided to dump Norton and endure fan ire because they believed Ruffalo is the better actor in the long run. Similarly, we believe the new Angular is your classic “one step backwards \ two steps forward” and part of the Angular core team’s plan for a richer ecosystem to help developers build scalable high-performing (and not just web) applications. We welcome the new Ruffalo version of the framework and embrace him as our true Angular.

Preordering the special edition of the game (and all the DLC)

In mid 2017, we planned our own “Order 66” on the existing AngularJS application. We would retire our current 500k-line, monkey-patched application and replace it with dyed-in-the-wool Angular 4 (the version at the time… yeah, we know it’s hella confusing) application that would bring us all the goodness of a next-gen framework — creating a better experience for both the user and the developer.

Oh, and we’d build it and release it in about a month.

Image for post
Image for post
“WHAAAT??”

Spoiler alert: we did it

Well, not exactly in one month, but close enough. In roughly the time it takes a pull request to get written and approved at some companies, we rebuilt our entire AngularJS application. A team of ten engineers rewrote every component, directive, and service of the legacy AngularJS application into the equivalent Angular 4 construct. In addition, we continued to release updates to the legacy application (about two a week), including bug fixes and minor enhancements.

How did we accomplish such an incredible feat? Did we sleep? Did we bribe Elon Musk for the secrets of time travel? In the next few articles, we’ll explain the steps we took, the challenges we faced, and how we ultimately measured our success through capturing the relative business metrics and KPIs.

But for the lazy, here’s the TL;DR:

We wrote a script to do most of the work ;)

Want to learn how we prepared for the upgrade? Read Eric Tsai’s post: Angular is coming: Prepare the upgrade.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK