BEN:
In the past, you guys have made references to Ward’s fashion style, and I had no reference for that. And then I was watching a video the other day, where he was introducing John Papa in the Style Guide presentation, and I was like, “Okay, I see what you guys are talking about.” [Chuckles]
CHUCK:
[Chuckles]
WARD:
Yeah.
[Does your team need to master AngularJS? Oasis Digital offers Angular Boot Camp, a three-day, in-person workshop class for individuals or teams. Bring us to your site or send developers to ours -AngularBootCamp.com.]
[This episode is sponsored by Wijmo 5, a brand new generation of JavaScript Controls. A pretty amazing line of HTML5 and JavaScript products for enterprise application development, Wijmo 5 leverages ECMAScript 5 and each control ships with AngularJS directives. Check out the faster, lighter and more mobile Wijmo 5.]
[This episode is sponsored by Digital Ocean. Digital Ocean is the provider I use to host all of my creations. All the shows are hosted there, along with any other projects I come up with. Their user interface is simple and easy to use. Their support is excellent. And their VPSes are backed on solid-state drives and are fast and responsive. Check them out at DigitalOcean.com. If you use the code “angularadventures”, you'll get a $10 credit!]
CHUCK:
Hey, everybody! Welcome to Episode 38 of Adventures in Angular. This week our panel, we have Joe Eames.
JOE:
Hey, everybody!
CHUCK:
Ward Bell.
WARD:
Hello.
CHUCK:
John Papa.
JOHN:
Howdy!
CHUCK:
LukasReubbelke.
LUKAS:
Yo!
CHUCK:
We also have a new addition to our regular panel, and that is Katya Eames.
KATYA:
Hi!
CHUCK:
Do you wanna introduce yourself really quickly, Katya?
KATYA:
I'm Katya Eames. I'm Joe’s daughter. And I'm just kind of a high school dropout programmer at the moment.
CHUCK:
Woo-hoo! Bill Gates! We also have a special guest this week, and that’s Ben Nadel.
BEN:
Good afternoon from Arlington, New York.
CHUCK:
Now you were on the show a month or two ago, but do you wanna introduce yourself anyway since you're regularly on the show?
BEN:
Sure thing. I'm CTO of a software service company called InVision App. We build a collaboration platform for design teams where people can create online interactive prototypes, and then share those prototypes within their company, within their social media circles, within whatever stakeholders circles they have at their means and get feedback and iterate on design. And try to get a better piece of software before they actually have to put in development time and effort. I'm a huge fan of Angular and a huge fan of JavaScript. I've been coding JavaScript for 10, 12 years or something. It's basically the first language I learned.
WARD:
Wow. There are some people who would say you never learned a programming language. [Laughter]
BEN:
Some days, it feels like that.
LUKAS:
Burn!
JOE:
Now, I just wanna empathize with all the listeners who heard Chuck’s introduction. I assume he pronounced your name correctly, Ben. Is that right?
BEN:
Yeah, “Ben Nadel”.
JOE:
Yeah, I wanna empathize with everybody who's like, “Nay-del, oh, my goodness! [inaudible]”
CHUCK:
[Laughs]
WARD:
I thought it was like saying “I’d like to have a latte.”
JOE:
[Chuckles] All these years, in my head, I was pronouncing it wrong, and I feel that.
BEN:
Oh, no, I've learn to respond with just about anything.
CHUCK:
With one finger. I mean.
JOE:
I wanna ask you really quickly, Ben. Haven't you been on the show recently?
BEN:
Yeah. About a month or a month and a half ago or something like that.
JOE:
I wasn't on that episode, so I missed out getting the show with the awesome Ben. But you said you're a CTO; so are you an actual, working CTO? Do you actually do some technical stuff or more management type guy? I would assume you're [inaudible] because based on how you blog.
BEN:
Yeah, I've come to realize that I'm pretty horrible at managing people, so I deal mostly with technology. I come from a full stack background, database, server-side client-side. And primarily, I kind of just go wherever the fire’s at right now. Trying to learn more about DevOps, but that’s a long journey it seems. Yeah, I spend most of my day doing technical work.
JOE:
Awesome. And for anybody who happens not to know Ben very well, you're one of the most interesting Angular bloggers out there.
BEN:
Oh, thank you very much!
JOE:
So everybody is blogging about, and you're always blogging about crazy things just like, oh, my gosh! I have to sit down and get a headache as I read your blogs. It's awesome.
BEN:
[Chuckles] I appreciate that. I walk an interesting line because I don't want to blog about things that are just in the documentation, because I know the documentations gets a lot of [?] but I don't wanna just echo it. So I try to find an angle or perspective on something that might be directing the documentation but talk about the hurdles that I had understanding it and the hurdles that I had implementing it or edge cases that I hadn’t considered. So I try to put my stamp on it, even if it's not necessarily something so far out there.
WARD:
It does seem sort of driven by the things that actually you run into as problems. I'm one of those guys that worry about people who do premature performance analysis and things like before they even get to the problem. But it seems to me that you have a lot of posts about that are sort of performance focused that arise out of your experience. So maybe you could tell us a little bit about how these performance questions arise for you and where it really seems to matter? What kinds of things are people doing where it really matters?
BEN:
Sure. So I just, maybe a little bit of history of the app itself. So about two or two and a half years ago, we did a complete, full rewrite of InVision as we know today it. And prior to that, everything was an individual page; you make a request to the server, and you get your response. And it was all these massive jQuery files. Because there still was a lot of interaction in the app, but albeit within a single page, not in a single page applications in a sense, but in a single page representing part of the application. And thousands and thousands of lines of totally incomprehensible jQuery stuff. We sat down and said, “Okay, we need to completely scratch this. Take what we've learned, learn from the mistakes we've made and rebuild it as a collection of single-page applications.”
And at the time, I think Base Camp had just come out with its new nested page model, and that we were using Base Camp at work at the time. And in terms of performance, we have looked at Base Camp and thought to ourselves like, “This is kind of the model that we wanna approach where the pages load very fast.” And even if there are pages that require some load time, if you’ve been to a page, and then you come back to it, it loads instantaneously. So when we said about rewriting the application from the ground up, we really wanted to leverage caching as much as possible -- clientside caching for data. And that was an interesting journey, especially considering we started working with Ajax requests, we're using the resource module, which I think at the time was just part of the Angular core. I think it may have been refactored out by now. But as far as performance, that was kind of our level of entry; we wanted pages to show up fast, but we didn’t really have anything else on the radar.
Over time, all of the performance things that I have dug into in the last two years have become symptomatic of actual use cases of the application. So if you can imagine that the application revolves around projects, and projects contain take screens, and screens contain links and comments and annotations, when we designed the product, we don't necessarily consider the scale that people are going to use it or imagine that people use it at the scale they end up using it.
So you have designs coming out of a product team that don't think about things like pagination or lazy loading or the built in features of manual sorting that makes sense when you have, say, ten projects but not necessarily when you have 800. The engineering team has had to work hand in hand with the product team to see where we can kind of give and take, where they can reform some of their designs to allow the engineering team an easier time to build better performance. We try to leverage Angular as much as possible to jump through as many hoops, and deal with as many tricks as possible to squeeze as much performance out of the application itself. But over time, as the application is growing, it's just a lot of performance problems have come to the surface.
CHUCK:
I wanna ask something about performance here. It seems like when we're talking about performance in something like Angular, I'm assuming it doesn't really impact the amount of bandwidth or other performance on the backend. This is strictly user experience. Or am I making an assumption that doesn’t hold?
BEN:
It is strictly user experience -- with the caveat that the more complex the user interface becomes, the more of data we tend to need to stream back to the client when we're instantiating a view. And you know, you have a lot of cooks in the kitchen. And unfortunately, what we'll find is that we'll have an interface that is working very well and then the designer is coming and will say “we would like this data point to be added here.” And so, someone has to wire that up on backend, and suddenly, that data comes from a query that hits the database on a column that wasn't indexed. And now, a query that took 4 milliseconds takes seven seconds. And everybody feels that impact very quickly.
WARD:
Is that a server side induced delay? Or is it because of the way you're handling it on the client?
BEN:
It's a server side. The client doesn’t necessarily need to know how that data is being gathered on the backend, right? It could be coming out of the cache; it could be coming directly from the database; could be coming from a variety of places and being aggregated. The client just needs to make the call to the server to get the data and then it's up to the backend engineers, the full stack engineers to make sure that that gets delivered most efficiently.
CHUCK:
So some of the user experience can be made better by making the backend more responsive?
BEN:
Oh, yeah. 100%. And then there are things… I mean, I know this is talk about Angular of course, but things like enabling gzip compression for JSON responses and putting assets behind CDNs, making fewer Ajax requests, aggregating data in a single request versus using several cascading or parallel Ajax requests. There's no magic bullet; it's a lot of trial and error in trying to weigh the complexity of the page versus the performance of the page and [?] globalization. It's definitely an art it feels, a lot more than a science.
JOE:
So I’d like to talk a little bit about Ward’s first topic, which was being driven out of actual things that you’ve encountered. Overall, how much do you feel like your team -- your application -- spends thinking of it in front of performance problems, right? Like, “Let’s design this so there's not a performance problem,” versus “we’ve got a performance problem. How do we fix it?”
BEN:
Yeah, most of our performance improvement is reactive rather than preventative.
JOE:
How do feel about that?
BEN:
I don't wanna say anything that’d get me into trouble, but…
[Laughter]
CHUCK:
I thought you were the boss?
BEN:
[Chuckles] The boss of the engineers. So we have our product team and we have our designers and our product leads. And one of the points of contention that we often have is how can we get the designers to think about user interfaces, and design user interfaces that are more conducive to performance? And the other side of that, we have the point of view that we don't want our designers to be constrained by that type of thinking; we want the designers to be thinking about the user experience and what feels as the most organic and natural and how do we create workflow that solves the most appropriate business problems. And not get weighed down with thinking, you know, “What is this going to feel like when it has to be rendered in a browser and deal with Ajax and deal with images?” And so on and so forth.
Historically, we have just built whatever they have sent us and put it into production and kind of react to performance problem that show up. We've taken a bit of a smarter approach recently where we do a little bit more of engineering validation before it actually moved into development. So the designer will work on an interface and a particular feature from the application and they get together with the engineers and say, “Okay, here’s what we’re envisioning. What are the red flags? Where do you see this going really wrong?” And that’s definitely helped. But still, we spend a lot of time being reactive. Because even when you see the design, even when you see it in local development and it's isolated, you don't get the wide range of natural use cases that you then have to account for once the feature has already been deployed.
JOE:
So I assume most people will have heard the quote by Donald Knuth, “The premature optimization is the root of all evil.” You’ve kind of indicated you’d like to be more proactive about it, but how do you feel like that plays in with what Knuth said?
BEN:
Sure. I think there are things that are premature and then I think that there are some best practices that can just be incorporated into all of your development. I mean, when we talk about web development in general, not necessarily just Angular, though some of these things become more pronounced with Angular, is that DOM document-object model mutation is the most expensive thing that you would ever do, right? You can iterate through a JavaScript array or execute a for loop one million times in a second. Probably it's not going to be too much of a burden on the browser, but you add a thousand DOM elements and the world is going to freeze momentarily.
JOHN:
Ben, if I can interrupt you for a second. That was a great point. So, we hear that a lot and I agree with you. But let me push back for a second from let’s say a junior developer level. The average developer hears a lot that, “Hey, do less DOM manipulation or don't do it at all,” right? But at the heart of it, templating really is DOM manipulation. So I'm trying to understand, as a developer coming to you hearing this, saying, “What should I be doing instead though?” Instead of doing that, what should I be doing?
BEN:
Sure. I don't think it's necessarily an “instead of,” I think it's more about timing and weighing responsiveness versus performance. So for example, one of the problems that we have often (and this is not problem that you solve once; you tend to solve it over and over again) is the idea of accidentally forcing a browser has perform a repaint where it actually has to render the DOM that you have changed. And you'll see this a lot of times with ngRepeats. Most problems are ngRepeatoriented simply because that’s where we get a lot of data and you put it on a page. And if you have directives that are on an ngRepeat element or you have jQuery plugins that are being integrated into ngRepeat or inside the content of an ngRepeat, what we often run into is something inside of that code, say like in linking phase in the directive where it has to calculate the dimensions of a DOM element or something like a jQuery plugin that’s trying to calculate something for a custom scrollbar. There's a variety of things that can happen where each time that ngRepeat element stamps out one of the clones, it has to then repaint the browser. And now, what you'll find, you move from being able to render a thousand ngRepeat items in a second to being able to render just a couple because browser is constantly stopping to repaint. So it's not that you are not doing DOM manipulation; it's that you're doing it a way, that allows the browser to chunk it at the end of a particular set of rendering operations, like the end of the digest cycle.
WARD:
But isn’t Angular supposed to handle that for us? In other words, if I give an ngRepeat, I said “bind to a thousand items,” I mean, I'm not literally expected it to whack the DOM a thousand independent times. I expect it to compose something and drop it in there. Are you saying that ngRepeat is inefficient? Or is it something else about ngRepeat, such as all the watches, is the problem child?
BEN:
Performance is really death of a thousand cuts, unfortunately. It's no one thing and no one thing solves it -- in my experience. So from the most basic standpoint, if you think about the ngRepeat directive and what it's doing, it's a single watch. It's not like it creates multiple watches for each items and creates one watch on a collection with granted that happens to do a lot because it has to compare the items in the collection itself. It’s the things that then get applied to each instance of the ngRepeat column that can then start to really accumulate hundreds, if not, thousands of [inaudible]
JOHN:
So let’s pull this out for a second. What we're really talking with an ngRepeat is the same thing we're talking in any language, where it's a for loop. We're doing something many, many, many times. And in Angular, many, many times happens to be at anything in the DOM, a lot of DOM manipulation but it's worth pointing out. And I think what you're trying to say is that there's things that you're doing in the ngRepeat inside that loop that you have to examine. It's not just that the ngRepeat is bad; by itself, it's fine but it's, what kind of watches are you adding? What kind of data is brought into there? Are you using the one time bindings? Are you using “track by”? Are you making http calls inside of there? Are you throwing away the data? How large is your list? Are you using virtualization? As you said, it's death by a thousand cuts but it can be very difficult, as you say, to diagnose what is the issue especially when… I find in my enterprise experience, it's not just one ngRepeat; it's an ngRepeat that happens to have another nested ngRepeat. And that’s when I usually run into problems. Is that something you see?
BEN:
Oh, my god. All the time. I mean, nested ngRepeats, I could think of several of my application that do that and cause a problem. So one that comes to mind is we'll have an ngRepeat that outputs a collection of titles and each title represents a project in the application. And then inside each one of those titles, we say “output the list of people who are associated with that project as an avatar.” So this problem is even more than just ngRepeat inside of an ngRepeat. It's that we also now have images involved. And what happens now we have an ngRepeat inside of ngRepeat that's rendering images and that’s sucking up http request out of the pool and can I do things like… JOHN:
And it's a very common situation. It's not something that very isolated. I mean, having nested sets of lists is actually pretty common out there.
BEN:
Absolutely. So one of the tricks that I've used is I will try to not build parts of the DOM tree until I actually need them. So you mileage is going to vary on this approach to depending on how that interface looks and reacts to user interaction. But one of the things that I'll do for an example is if I
have an ngRepeat that has elements that have hover states and inside of that hover state, you have DOM elements that gets shown that aren’t there normally, what I will do is actually create a compile directive that will subsume the ngRepeat before the ngRepeat execute go through and find these common elements that don't necessarily need to be shown right away. Physically pull them out of the DOM before the ngRepeat has even compiled itself. And then what I can do is use event delegation after the ngRepeat has rendered. So once the ngRepeat renders and the user is mousing around, say they mouse into a particular ngRepeat instance, I can track that at a delegation level, say, “Oh, you have not been into this project or this title before. Let me clone link and inject the elements that weren’t there in the first place.”
So what happens is let’s say for example, I have an ngRepeat of 100 items and then inside each of those, I have ten items that have to get listed in some sort of hover state. Instead of rendering a thousand DOM elements with potentially a thousand launchers, I can implement 100 and then as each one gets rolled over, I can clone and link ten additional things. And then I can rip them out of DOM when the person mouses out of that element. I mean, this is obviously, one of the more advanced things that I've ever done with Angular, but once you can like wrap your head around how compiling and linking and transcluding works, it kind of gives you the opportunity to really reach in to the compile and linking life cycle, and say, “Oh, let me not link that yet. I'll link that later if I need to. And let me change this so that I whip it out of the DOM but I have a marker that I can get back to, so that I know what I'm talking about.” And John indicated things like the one time bindings, you can do which that becomes a whole new adventure if you get in with cache data. I mean, it's very exciting.
JOHN:
It is very cool and it's a lot of fun. I agree. I think types like us, we like dive into those things. They can be rabbit holes at times too. Ward’s really good at doing this for me when I'm coding with him is “Wait a minute, John, let’s think about this problem. Instead of attacking the performance issue, maybe we need to relook at how this screen and this experience has been designed.” And so in some cases, maybe we have too much going on in the same place and that's the reason we have 14 level of nested ngRepeat, for example. [Laughter]
JOE:
Yeah, I don't see a problem with that.
JOHN:
[Chuckles] “Hey, let’s make a single web page with 48,000 things on it.”
WARD:
Right. And the way it often starts is the designer will come to you and say, “That’s what the user wants.” And you really look into that and say, “Did the user really say that or is that what they were used to seeing in something else? Can we achieve…” but this goes back to where you started from almost, when you're talking about that dynamic of the developer designer divide. And when they become separate departments and it just sort of flows downstream one way and there's no conversation, you can get locked in the ways that a lot of time, designing around something that if you sat in front of the designer and the user [?] and said, “I wonder if we can look at what your workflow is again and see if we can figure this out together, we could get some place good.”
JOHN:
Yeah, one of my favorite ones I hear about a lot, this is something that recently happened was let’s say you’ve got a screen read, you’ve got enter a bunch of data for each person. And maybe let’s say you’ve got, maybe buying tickets for an event, like maybe go to see a rock concert – ACDC, let’s say. And you're doing that, and let’s say you have to enter a bunch of fields for each person who's attending. Would you expect, in the old style world, you'd have maybe 7 people attending, all seven people to be flowing in a vertical directions; you scroll, you enter data, you scroll, enter data, etcetera. Or would you possibly think that redesigning something like that [?] performance issues to say, “show me tickets for the first person” and then press the button, do a gesture swipe, whatever your interface is, and show me person 2. Or when it's simply completed with person 1, have it automatically change the view to show person 2. Meaning, don't show all seven at the same time. Actually use UI view or the router or other ng constructs so you're actually destroying the old data on the DOM and bringing in new, so you're not constantly dealing with these things. And that’s just one example of the ways I think designers can be our best friends is they can help us solve these problems without technical solutions just simply by showing us easier ways to present information.
BEN:
Yeah, I mean, I agree a thousand percent with what you're saying. And everyone has their own type of constraints in terms of the team dynamic, as well as also being constrained by what is already out there in the wild in terms of your product’s feature set. It's one of those things where let’s say you release a feature that's not very perfromant and you have a million users and then you look at your database and you say, “Oh, 2,000 people are using this feature and it's not perfromant.” Is that a sufficiently small number of people that I can justify removing it to increase performance for everybody else? And it comes not just an engineering question at that point; it really becomes a product question and a marketing question and a sales question and a support question. Like, you start moving features and now the support team is going to start getting tickets about “where did this go? I can’t find the feature anymore.” And the bigger the product is, the bigger your team gets, the more people you have to have on the same page agreeing with the same outcome before you can really start to implement things.
JOHN:
Yes, you might. But I think you need to look at this the same way and I need to look at it the same way I look at technical problems. Meaning, nobody likes it when you walk in a room and say, “Hey, the thing you wrote sucks; you should do it this way.” So we shouldn’t be going to designers as technical people saying, “Design it differently to help me.” But instead, maybe the better way to go is to say, “Look, I've thought about this and I'm having technical problems with this design. Could this be solved in this way? And look, I just did a quick mockup with the same code to show you how you think it could work.” And then you know, kind of go back and forth. You know, don't just come in with the problem is what I'm saying. Come with a partial solution to show people what you're thinking. Because we don't talk creative and creative people don't talk tech -- not always. So we have to meet them halfway to say, “This is what we mean by this.” So I think when you put some skin in the game, it really comes out a lot better.
CHUCK:
I wanna kind of change topics a little bit, mainly because I think we all deal with the difference between designers and developers. And I think we've pretty well covered how to have those conversations. What I'm curious about is, so you build a feature into your application and your test application runs fine, perfromant, whatever, blah, blah, blah. And then somebody comes to you and says “I've got 20,000 records in here that it's trying to show and it takes forever to load up.” So how do you go about actually figuring out where the performance issues are so that you can get in and fix them?
BEN:
So the first thing I'll do is sometimes we'll look at what has changed on that page recently. Because often times, we don't go from most people using some small number and then someone using a large number. Usually, we have an ever increasing usage pattern and then suddenly something is really slow. So, one is just looking at the Git commit history for a particular set of file. Saying, “did anyone say something suspicious that maybe we could just do a quick fix.”
If that doesn’t happen and then you usually, the next step for me is digging into the chrome developer tools. And I have historically been a huge fan of Firefox and especially Firebug, which I don't know how I did web development before Firebug. And chrome dev tools, I was like, yeah, it's like the same thing. Until I've found all the profiling and the heap allocation monitoring and the painting and stuff. And oh my gosh, this is like the most amazing thing I've ever seen in my life where you can click on the page and you see the stack traces of all the JavaScript actions that are taking place and where all the painting is taking place, and what's blocking and forcing the browser to repaint and what initiated those requests and it's seven layers deep in the JavaScript files.
The chrome developer tools are mind bogglingly awesome. And that’s definitely my go-to for figuring out where the performance problems are coming from. Because not only will show you where the kind of the run time problems you're having where you execute an action and then it takes place and now you're seeing why it's slow. The other really amazing thing about the chrome developer tools is the ability to look at the memory usage overtime. Some of the performance problems we see aren’t from the individual actions; it's from the accumulation of memory overtime and why that memory is not being deallocated. And you can see, you can turn on this heap allocation monitoring where you can go through your application. And it's recording to see what memory has been allocated and you can see what memory is not being de-allocated and what parts of your application are maintaining references with that memory.
You can say, oh… I mean as a very concrete example, I use ui-if heavily on the application because unfortunately, a large part of our application is still running on AngularJS 1.0.8. There are some constraints that have not allowed us to upgrade very timely. So we had ui-if before we had ng-if. And ui-if had a really serious problem where when you destroy the element with ui-if, it was removing the DOM element and then calling the destroy event. And the problem was any jQuery element or jQuery plugin that was attached at that point when the DOM element gets removed, jQuery goes through and deletes all the data associated with the elements to free up the memory. But then the problem is that the plugins don't necessarily know what to be destroyed until the destroy event I called. But at that point, they don't have references to a lot of the data that they were using to manage their own internal memory structures.
So you end up with these memory leaks that happen overtime and you can’t necessarily see that until you're using the application. You're looking at the memory allocation in chrome dev tools, you're seeing, “Oh, I see all of these references coming from this slider plugin which is creating an iOS-like scroll bar And it's not been able to be destroyed because the element that contains it is being managed by ui-if.” And then you have to go into ui-if and patch it, so that you reverse the events that take place. You make sure that it crawls the destroy event before removing the DOM element and now some of that huge memory problem is freed up. And now you’re doing your test again and you say, “oh, now the page is x% better, but now that I've removed that layer of problem,” I'm seeing now, “Okay, I have this forced repaint inside this ng-repeat,” or “I have this timers that are firing too often.” And all of that is visible inside of the chrome dev tools. It's quite a marvelous tool.
JOE:
So for somebody that’s listening in here and thinking, oh, wow, that sounds super awesome but the chrome dev tools are kind of a big thing, right? Especially the performance stuff. Where is the great place for somebody to go and start learning how to utilize the performance pieces of your chrome dev tools?
WARD:
Yeah, another way of taking that is I would love to watch you… because you always do these great little video pieces in your posts and I’d love to see you sort of take us on a journey through that analysis. So how the chrome tools revealed it to you and all that stuff? I know you don't have anything to do, but… [Laughter]
BEN:
It's interesting, right? So we often talk about imposter syndrome in the engineering world (I assume this exists elsewhere as well.) As much as I love talking about the stuff that I talk about, when it comes to things like the chrome dev tools, I mean, I learned a lot of what I know watching presentations by Addy Osmani and Paul Irish and a couple of other people on the chrome team. And you watch their presentations and I feel super insecure about, “oh, I'd be talking about some tiny portion of this. I thought I’d get half of it wrong. And these guys are so amazing and they obviously know the chrome dev tools inside and out.” But I’d have a lot of practical experience at this point. And it’d be something that I would love to kind of build up the courage to do for sure.
WARD:
I think I'm going to plug you here, because in each of these little performance things that are on your blog posts, that we're having [?] and you have these little vignettes [?] to discuss something. And you bring the chrome tools up and you use it just as you need to and only so much as you need to in order to illustrate the point that you're making. And I find that vibe. Because otherwise, I know the things you're talking about there with the audience and Paul Irish and stuff and they are wildly impressive, but I wonder if I'm the guy who can ever take the time to learn all that. And you kind of bring in down in digestible pieces. So I think you should take advantage of the fact that you're an impostor and just do what you're thinking is superficial because that’s exactly what the most of us want.
BEN:
Well, I'm sold. [Laughter]
WARD:
Way back when, earlier in our conversation, one of the interesting things that Ben was talking about was when you had that ngRepeat problem and how he did sort of just in time view construction. And then we got into “Hey, can you design yourself out of having to deal with that problem at all?” I think we all agree that that would be great if you can. And then Ben comes back and says, “You know what, sometimes, you got to live with it.” So what are you going to do if you’ve got to live with it? And that was when you were talking about what I'm calling, just in time view construction. So even though if you would look at the template the way that it was originally written required you to build all those things a thousand times, you're doing some magic in there that says, “Not really. I'm going to fake it here for a while until somebody actually needs to see that 30throw and then I'll create the view for them.” Is that approximately what you were saying at the time?
BEN:
Yeah, 100%. If you think about the DOM structure and the way Angular consumes the DOM, right, so it walks down the DOM and it's running all these compiles. And then when it hits the bottom of a particular DOM tree, it's done compiling, it starts linking them back on the way up. And then at each particular level, it executes the compile based on priority settings, the [?] priority settings and that it takes terminal and transclude and things [?]. So what I'm doing is essentially before the ngRepeat actually does its thing, right, it's just a single element on a page or multiple elements if you use it in a block style syntax (which I almost never do.) But if you think about before, it does its actual iteration or it's just a single element. And that element then, during the linking phase and the subsequent watches gets cloned and linked and appended to the DOM.
What I'm doing is kind of going a step above that or a step before that in the DOM. I'm saying, “Okay, is the compile process is walking down the DOM? Let me stop it where it is and find the ngRepeats internally and then find the particular element that I wanna remove.” So remember, at this point, it's still just a single element on the page. And I pull out the element that I wanna defer until later and I run it through the compile service. And so the compile service will return a link function that will allow me to clone it later on. At that point, the compile process then continues to walk down the DOM. It hits the ngRepeat. NgRepeat compiles its element less the components of it that I've already stripped out of the DOM. So it's actually compiling fewer bits of data. And then when it goes to iterate through its loop and it clones and it appends, it's not including the data that you ripped out.
So then when I do is I listen for particular events from the user like a mouse enter, and I will take that compiled element that I've ripped out and got the link function to. I use the link function to clone the extracted template and then inject it into the particular DOM element that the user is mousing over which is the ngRepeat instance. And at that point, it will link to the appropriate scope. This is interesting point, right, each ngRepeat has its own scope. So as the user mouses into the particular ngRepeat instance, I have to determine the scope from the DOM element itself. Angular attaches scope using the .scope method. So I can say, “Oh, this particular item is associated with this particular scope. So I can grab that scope then take that linking function that I got during the compile phase, link the clone element to the particular scope and I inject it to the appropriate ngRepeat element.” In which case, all of the directives inside that will now fire and work all their magic. And then if the user mouses out, as an example, then what I can do is I can call a destroy on that scope that I was using before, rip those elements out and now the DOM is back to where it was for. It's not simple when you're jumping through hoops, but that approach has typically had a very huge performance impact on page rendering for me, personally.
WARD:
The visual effect (just for those trying to imagine it) is as you move from item to item in the list, the detail appears when you enter it and then the detail disappears as you move away. So the user experience is the detail comes into view and the detail, the stuff that you're working out and plugging back in again on the fly, that comes into view as the user is interested in that item. But then as soon as they move on to another item, it just disappears from view. And that’s kind of a compromise with the designer who would have thought that all those things were there instantaneously. And you said, “Well, you know what, lets negotiate…” you kind of negotiated with them, didn’t you, in a sense and saying, “for this little trade off in user experience which is they'll only see the detail when they visit the item, I can give you the performance you want.” And that worked out, right?
BEN:
Yeah, some of those are discussions and some of those are kind of executive decisions. [Chuckles] Sometimes for example, if there's no DOM element to begin with and then you inject it certain things like fading in, become a little bit more problematic. Because it wasn't that the element had no opacity when you hover into it, so the element didn’t exist. So there's nothing to fade in. So sometimes, you have to say, “Okay, it's not going to fade in. it's just going to show. And I'm not going to tell anybody about it because this is going to fix a lot of performance problems.” And then if someone wants to complain about it later we'll address it more effectively. With ng-animate, some of those concerns become alleviated because it helps with the ngenter states and so on and so forth. Sometimes, it has to be a conversation. And sometimes, something is so glaringly a performance benefit that I find and maybe this is use of my title, that I just have to do that without asking.
JOE:
So one of the things that struck me about your scenario is it's fairly complex the steps that you're going through grabbing a link function, holding on to it until later, watching mouse over, etcetera.
Can you approximate some of those just by throwing pieces inside of an ng if?
BEN:
It's an excellent question. So again, a lot of the hoops that we had to jump through is the fact that we're running 1.0.8. And a large portion of the application which didn’t have ng-if, we used the Angular UI module to fill in some of that gap. So that gets you part of the way because certainly, you can turn on a value and that value can then determine whether or not the DOM element’s in place. The next issue that you run into is at “Okay, well, what that means then is I have to have something that’s still listening for the event, like the mouse into [unintelligible] specifically. And it has to set some sort of a view model and then something like the ng if has to be watching that view model for changes and then it has to do its thing. So you're definitely getting a good performance boost in that you are deferring a portion of the DOM. But you're still also then incurring watches for the view model that’s managing the ng-if state. Now, granted, there’s still going to be a huge performance increase because you go from whoever many watches are inside that DOM sub tree, to just a particular one for the ng-if. So I'm certainly not down playing that. It's a huge performance boost, absolutely but not necessarily exactly the same thing.
JOE:
Not quite as much. But when you say hover off and the ng if goes back to default, it rips the DOM, those pieces back out of the DOM, right? Then do you go back to… you don't keep accumulating watches. If you had hover over all thousand items, you don't have another thousand new DOM nodes that have a whole bunch of watches associated with them, right?
BEN:
Right. One of the steps is when the person mouses in, you find the scope that you need to bind to. But then you don't actually bind directly to that scope. What you do is you create a child scope that uses that ngRepeat scope instance as its prototype. And that way, you can destroy that scope later on when the user mouses out. And that will automatically unbind all of the watch bindings and the event handlers and anything else that’s listening for the destroy events such as jQuery plugins that are integrated properly. So you don't accumulate watches if you're being careful about destroying scopes. But if you're not careful, then yes, you accumulate and you'd end up with little weird behaviors and watches that fire a lot and event handler that fire too often and so on and so forth.
JOE:
So if you're on a latest Angular and you're using ng-if, do you get the same benefit or do you have to go back to manual?
BEN:
No, that’s exactly what it does, it creates a child scope and then it destroys the scope. Ng-if is amazing. I love it.
JOE:
So I know I've been going for a little while here. I wanted to ask you some of your opinions about Angular 2.0. I don't know if you just happen to see Dave Smith’s talk at ng-conf or if you played around with Angular 2.0 and its performance?
BEN:
My experience with Angular 2.0 is just from some of the presentations I've watched. I'm not good with names. There's even one who did the stat table and they had like a thousand items.
JOE:
Yeah, Angular + React = Speed?
BEN:
Yeah that one. I watched that a week or two ago. It seems pretty amazing. I mean, I just this morning finished listening to the previous Adventures in Angular podcast. And the hardest thing for me to wrap my head around is the idea that’s kind of the acyclic model change tree. I don't quite understand what everyone was talking about.
JOHN:
The unidirectional data flow.
BEN:
Yeah, thank you. That’s what it is.
JOHN:
Exactly.
WARD:
Got us all spooked. [Laughter]
BEN:
It sounds really fast.
JOE:
Ward is ready to bolt any moment.
WARD:
Well, I'm not convinced they know what the implications are.
BEN:
[Chuckles]
JOHN:
So devil’s advocate here, right? You know, unidirectional data flow with order events speed and all these fun stuff is great, but if you're running in the same direction all day long, yeah, you're superfast but what about the functionality? I think that's the big question we're all hoping to hear is how do we replace what we used to have with these awesomeness with the two-way data binding and everything else in the new Angular 2.0. And that’s the stuff that they didn’t show code examples of that at ng-conf, but that’s the kind of stuff that they are working at right now which I think all of us are waiting for.
JOE:
Ben, have you read Victor Savkin’s blog about change detections in Angular 2.0?
BEN:
It sounds familiar. I think I have it [unintelligible].
WARD:
Yeah, but didn’t make me feel like I got the answers I was looking for. And it's all ponies and rainbows.
JOE:
Another pretty interesting piece to get some of these information is John Lindquist just posted to egghead.io the first video on Angular 2.0, talking about template languages. We actually… it kind of answers one of those questions like two way binding, how do we get two way binding in Angular 2.0? And it was pretty cool.
BEN:
One of the biggest hurdles for me right now, I'm kind of wrapping my head around the Angular 2.0 stuff is all of the examples that are being shown in the videos are I guess AtScript and now they are TypeScript, I guess. Misko keeps saying, you know, “Oh, we're not going to force people to use ES6. We're not going to force people to use TypeScript. You can still use the “regular” JavaScript syntax.” But I feel like I haven't seen an example of what that looks like yet. It's hard for me. It's like, I don't wanna look at CoffeeScript necessarily. I wanna look at JavaScript that I can build my mental model in a way that I feel most comfortable. So if I could see how these components and these type annotations and these template annotations are actually being translated into something that feels a little bit more familiar, then that will be, “Oh, okay, I see what the migration path is because you know, you don't have the directive configuration object anymore. You're doing it this way for as object properties or something.” I'm making that up, but...
JOE:
There's a couple of problems with it right now. I mean, you totally can, obviously because it doesn’t run unless it's ES5, right?
BEN:
Right.
JOE:
Browsers don't run ES6; they run ES5. So obviously, it does work in ES5. The question is what does it look like to author ES5? The other problem is right now, it's using Traceur to transpile. That’s the only transpiler they have that supports the… and really, what they are showing isn’t AtScript or TypeScript so much as it's ES6 plus the annotations. And Traceur supports the annotations and nobody else does. But really, as far as I understand, that’s all that is ES6 plus the annotations. That’s the only real important part. They do take advantages of some other stuff in other places, but mostly what you're saying is just ES6 and annotations. So when it compiles out, the problem is Traceur is terrible at making readable ES5 code.
WARD:
Well, I don't think they are going to have that problem, Joe, with Typescript 1.5. That was supposed to be out by now, but 1.5, generates ES5 and it's a lot cleaner.
JOE:
Yeah, Babel is working on supporting annotations, so it should be possible to use Babel as well so we can get a better idea of what that might look like. But annotations for example, they are simply actually like a weird…. they are just a property of the class.
WARD:
A static property of the class.
JOE:
Yeah.
WARD:
I think Ben speaks for everyone in saying we'd like to see more visibly what that looks like, but… [overlapping talks]
JOHN:
We need to see some code.
WARD:
We need to see some code and see more of it and see what really happens when you go whole hog this way.
JOE:
I will say one thing. I've given a couple of presentations now on Angular 2.0 and have some pretty interesting conversations with people. One of the things that I think has come out of me prepping for all this and giving these presentations and talking to people that are looking and saying, “Oh, this and that, “ is I think that one of the things that Angular 2.0 is going to end up doing in our industry is causing a lot more people to say, “Hey, I think I'm going to put in a transpiler and actually start authoring it in ES6, which because it's kind of beautiful and Angular makes that more obvious, that hey, ES6 authoring is really nice and beautiful. And then we'll all going to benefit because ES6 is just a little bit nicer than ES5. So I'm actually kind of happy about this that we're seeing all these examples in ES6. And I think my guess is by the end, it will be obvious that you can author in ES5 or ES6, but it's just easier and nicer to author in ES6 and that a lot of people will start doing ES6 transpilers. And there are projects that are doing it now. I don't know what percentage of projects use ES6 transpiler, but I would guess its pretty low.
BEN:
And I think historically, you'll see people migrate when they start to feel enough pain. Like when I first wrote CSS, I never learned about LESS or SASS and then I started to fool around with it and then I was like, “Oh, this is mind blowing. How could I ever have done work without this, previously?” And you know, hopefully I'm not in a transpiling step of my journey yet, but I think once I see that, you see the power of it and be like, “Okay, I get it. This is how I have to do things.”
JOHN:
The first thing I do when I use Typescript and I'm a Typescript fan. And in full disclosure, I have a Typescript course on Pluralsight with Dan Wahlin, but I don't use TypeScript a lot. And the reason is I don't use a lot of its features but I still use it. So let me explain that. I write JavaScript inside of a Typescript file, so I get the basic design time and development experience checking of things that I need. So it helps me there. I don't necessarily take advantage with interfaces and classes and all that stuff all the time. But I do like how the Typescript’s compiler will check for you to make sure that you're actually… you’ve got your types are setup properly and it can infer different things for you and check your function calls and some things with intelisense which is great.
JOE:
That user experience is a lot better in Visual Studio, obviously.
JOHN:
Yeah. And things like OmniSharp can help you with that too on the platforms. So I guess my point here is that you don't have to be full hog on to a transpiler to start with Typescript. You could simply just do Es5 or ES6, writing a TS file inside of the Visual Studio or any of the other OmniSharp type tool.
BEN:
Yeah, it's interesting. My biggest hurdle is always “are these tools always solving pain that I'm actually having?” Because you know, honestly, there's so much debate about what the problems with JavaScript. Like I can’t go a week without seeing some sort of tweeted photo about the JavaScript Bible versus JavaScript Good Parts in the same photo. I think it's funny and I get it. There are a lot of quirks. But at the end of the day, JavaScript is not that weird. There are a couple of weird things wrapping your head around lexical bindings, enclosures and understanding this bindings and how those can be changed dynamically. We solved those problems. It's not like those, I mean you’d have to run them, right? But beyond that, I don't know, I don't find JavaScript to be the hurdle. The hurdle for me is architecting a large, complex application. And I don't think syntax is what’s holding me back.
JOHN:
I agree and even in ES5, ES6 is why I like ES6 but I'm not full hog into going to ES6 yet either simply because while its cool, it's made my life easier, it's not solving the biggest problems I have right now, which are architecture.
JOE:
I totally agree with you guys. I’ve really never used a transpiler in a production environment, but having given these Angular presentations and having to build everything in ES6, I'm actually kind of finding that oh, kind of bends experience. I have kind of the same experience with SASS; it's like, “This is actually nice. I didn’t really know what I was missing.” Now that I've seen it, maybe I'm going to have a harder time without it.
JOHN:
Yeah. What's nice is at least with Typescript or in Babel even, you're still writing JavaScript, right? You're writing ES6 type stuff. It's unlike things like CoffeeScript where you're doing something completely different in a lot of cases with different syntax.
WARD:
I'm not sure I need all that other stuff, but what I do need is I have a problem with memory loss, which is I can’t remember my own APIs the minute after I write them or anybody else’s. So I always got the browser open and I'm searching in the browser for “what the heck is the signature for that?” And if the tooling can help with that, I may be seduced back into it. I know we're coming to the end. I wanna ask a somewhat related question, which is I'm struck by, Ben you were talking about how you have this app and you were stuck in Angular 1.0.8. You couldn’t even get to 1.2 and we're up to 1.4 and 1.5 is coming. You're back there in 1.0.8. What are the prospects in your world -- serious prospects -- of ever moving or moving to 2.0? How do you even think about bringing your customers, your clients, to next versions?
BEN:
Great question. Our biggest sticking point for the upgraded self is the limitation in double transclusion on the same element. And specifically, our views, all of our nesting of views were originally built as ng-switch statements, but that had ngIncludes that build all of the nesting. And when Angular 1.2 came out, you couldn't transclude two directives on the same element. They have since loosened some of the restrictions where they can do that. But I think ng… I don't know, there's one that we might be able to actually upgrade at this point, I haven't checked. But that's the biggest thing simply because it's one of those things because you have so many cooks in the kitchen, where if nobody is touching the application, I could probably get through the entire scope of all of the changes in the couple of days. But the issue is that by the time I get to the end of my [?], the rest of the team has committed fifty seven different commits on GitHub. And all of those things have merged conflicts now and they’ve built new stuff that doesn’t have these new changes and people aren’t pulling to develop as fast as they should. And that's been our biggest hurdle.
WARD:
You can’t say, “All right, we're having a migration spread while everything else is off?” You can’t do that?
BEN:
So much momentum with no breaks. It's hard to get anything to slow down, unfortunately. I mean, this is a cultural thing at the company. It's not you know, to each is their own. But one thing that I've thought about doing is actually getting a version of Angular 1.2 and kind of going in and actually just monkeying with the source code to allow for the double transclusion. Because behind the scenes, it uses the $tbl or tlb. I don't actually know what it stands for. And just turning that on in the source codes that I can do this and then slowly migrating the code to being a more appropriately formatted.
CHUCK:
All right. Well, I'm going to cut us off. We've been at this for over an hour and we usually try and keep the show to 45 minutes. [Laughter]
BEN:
Sorry.
CHUCK:
No, it's all good.
WARD:
You're off, man. That’s it.
LUKAS:
Nailed it.
BEN:
[Laughs]
CHUCK:
It’s just, It was so good, I didn’t wanna make it end, but we got to make it end. Let’s go ahead and do picks. John Papa, do you wanna start us with the picks?
JOHN:
Sure. So I'm bringing up a topic that I've loved in the past and that is BrowserSync.io. And the reason I'm bringing it back up is recently, I was going through my gulp course and we're [?] some of the files and I saw on Twitter that BrowserSync, the Twitter handle for it, was talking about a new version of it when it came out. So I went and checked it out. They have some wicked cool stuff in BrowserSync. And the biggest part that I love is they’ve now got support for WEINRE, that’s the web inspector remote or weinre or however you pronounce that. So you can do all these remote debugging with your browser. You can also set up BrowserSync to change all the toggles on the fly inside the browser. So you might configure them at design time with gulp or grunt, and then run it, but then you can actually change it on the fly without having to restart the server. And my favorite part is now you can set up all this remote debugging and throttling too. So you can say “let me spin up four different servers: one on 3G, one on 4G, one on Wi-Fi, one on throttle completely,” and then run them on all different ports simply by setting a button inside the browser with BrowserSync. So if you haven't checked that BrowserSync, it has changed and it is utterly awesome. Such a time saver these days.
CHUCK:
Awesome. Joe, what are your picks?
JOE:
So my pick is going to be the egghead.io video I mentioned earlier with John Lindquist about the Angular 2.0 template syntax. It's an excellent little… it's only 11 minutes long but really shows some cool features and pieces of Angular 2.0. Great way to start learning a little bit about Angular 2.0. So that will be my pick for this week.
CHUCK:
All right. Lukas, what are your picks?
LUKAS:
So I have two quick picks: one is if you go to the InVision app website, you can actually sign up to win a t-shirt. I gave Ben $200 and he just gave me one. Totally awesome t-shirt. Actually, I love it. I wear it like six days a week and only take it off on the seventh day to rest and wash it. This is kind of meta, but I'm super stoked on the show. I didn’t even say anything really on this episode, but it was just my mind was reeling. Like, ton of great information. So my pick for Adventures in Angular is Adventures in Angular. How meta, meta.
CHUCK:
[Chuckles] Katya, what are your picks?
KATYA:
My picks are Welcome to Night Vale because everyone needs a podcast about totalitarian government.
CHUCK:
That’s the second or third time I've heard about that one.
KATYA:
It's really good. Really odd, but really good.
CHUCK:
All right, Ward, what are your picks?
WARD:
Well, I broke the leg off my couch recently, so I'm picking Martin Heidegger’s Being in Time, which philosophical [unintelligible] 512 pages and just lifts up the edge of the couch. [Laughter] I don't recommend reading it, [chuckles] exactly, but it does hold the couch. Or after you’ve got the couch levelled, there's a, from a performance perspective, I deal with business apps. I'm always looking for a grid and I haven't found a grid. And recently, something stumbled across my attention called Angular Grid, which is a guy who took the ideas in Slick Grid, which is a very, very fast business grid with column pinning and grouping and stuff like that. And he took some ideas in there, but made it a truly Angular-ish Grid. And I'm going to put the link to it on our show notes. And if you are writing a business app and you’ve been told that you must have a grid, a data grid like everybody’s afraid of who's a developer, this is one I think is worth checking out. I can’t speak from experience, but it's the first thing I've seen come along in a long time that looks like it's the perfect marriage.
Open source fast grid for Angular. So check it out.
CHUCK:
All right, I’ve just got one pick. I'm pretty sure Joe’s picked this one one the show before, it's Steelheart by Brandon Sanderson. Just finished reading it.
JOE:
Yes!
CHUCK:
It's awesome. I loved it. Got to pick that.
JOE:
You got to read that second book now, Chuck.
CHUCK:
I know. I'm going to buy it here pretty quick. Ben, do you have some picks for us?
BEN:
Sure. Two picks. I'll keep it quick. One is a headphone extender that works with iPhone headphones. So for the longest time, my iPhone’s headphones weren’t long enough to get to my monitor. So I lived in this world where I had my iPhone headphones for music and then if I wanted to make a call over Skype, I had to switch headphones. And it's a real pain. And the extender, what it allows is the audio and the mic to work through my iMac here. And it's changed my life. I'm in a one set of head phones world, and I'm never looking back.
WARD:
Well, you can stop visiting the chiropractor. [Laughter]
BEN:
It's awesome. My non-technical pick, I was in the barber the other day and the movie Any Given Sunday on the TV. It's an old football movie with Al Pacino. It struck me as being just an excellent example of team dynamics. And this idea like there’s this football team and you have kind of the old guy where you have these guys who are aging out. And you have the young hotshots that are coming in. And it's all about earning the right to just respect people and to show your voice. And also at the same time, trying to hold on from the people who had been there for a long time. And it's interesting. I feel like from an engineering standpoint, you get a lot of that same problems or dynamics in an engineering team where you have people that come in that wanna start using NoSQL database and they wanna start using ReactJS. And they don't necessarily take the time to learn from the old guy, why are we using MySQL? Why are we using AngularJS? Why are we doing all these things and understanding the breadth of the application. I don't know, it just struck me as such a great sports parallel for I think what we see from engineering team dynamics as well.
CHUCK:
Very cool. All right. Well, thanks for coming, Ben.
BEN:
Absolutely.
CHUCK:
We really appreciate that. Do we have any announcements about conferences?
JOHN:
Ward?
WARD:
[Chuckles] Let’s just keep telling them. Come on, there's Angular U in June. Come and see it. It will be all about what Angular 2.0 and friends all the stuff that have to do around it. What the early actual experience is because it will have had some time in the field by that time.
JOE:
Yeah, same thing for ng-vegas, tickets are still on sale. And I'm excited to have John Lindquist come in and teach. And I'm excited for Angular U as well. Really excited for that. I'm excited to my talk.
CHUCK:
[Chuckles]
JOE:
Not because I like listening to my self talk, but I enjoy the research phase of getting a talk and actually learning stuff really in-depth. So, some Angular 1.0, Angular 2.0 stuff at my talk. I'm excited for that. And I'm excited to go down to Vegas and chill out. It will be fun.
CHUCK:
I thought you were going to say, “It's not that I like hearing myself talk; I like *you* hearing myself talk.” [Laughter]
JOE:
I like other people hearing me talk.
WARD:
Yes, he likes basking in the glow of applause. [Laughter]
CHUCK:
And long walks on the ng-beach.
JOE:
[Chuckles]
CHUCK:
All right, well, with that, we'll wrap up. We'll catch everybody next week!
[This episode is sponsored by Mad Glory. You’ve been building software for a long time and sometimes it gets a little overwhelming; work piles up, hiring sucks, and it's hard to get projects out the door. Check out Mad Glory. They are a small shop with experience shipping big products. They're smart, dedicated, will augment your team, and work as hard as you do. Find them online at madglory.com or on Twitter at @madglory.]
[Hosting and bandwidth provided by The Blue Box Group. Check them out at bluebox.net]
[Bandwidth for this segment is provided by Cache Fly, the world’s fastest CDN. Deliver your content fast with Cache Fly. Visit cachefly.com to learn more.]
[Do you wanna have conversations with the Adventures in Angular crew and their guests? Do you wanna support the show? Now you can. Go to adventuresinangular.com/forum and sign up today!]