096 JSJ The Challenges of Large Single Page JavaScript Applications with Bart Wood



01:29 – Bart Wood Introduction

02:12 – The Frontend

02:48 – Working on Single Page Applications

05:56 – Limitations

09:51 – Online Practice Management Solution

11:40 – Other Storage Mechanisms/Data Structures

20:14 – Nesting

21:04 – Memory Testing

22:19 – Cleaning Up Views & Listeners for Performance

24:02 – Chrome Profiling Tools

32:10 – Why You Shouldn’t Build Large Single Page Apps

35:47 – React

37:56 – Maintaining the App


Next Week

Gulp.js with Eric Schoffstall

This episode is sponsored by

comments powered by Disqus


[Hosting and bandwidth provided by the Blue Box Group. Check them out at BlueBox.net.]  [This episode is sponsored by Component One, makers of Wijmo. If you need stunning UI elements or awesome graphs and charts, then go to Wijmo.com and check them out.]  [This episode is sponsored by Peer60 Incorporated. Peer60 Incorporated knows that the best JavaScript developers hone their skills by listening to JavaScript Jabber podcasts. If you’re looking for a frontend or full-stack development opportunity helping Fortune 100 companies understand their customers better, email jobs@peer60.com.] [Do you wish you could be part of the discussion on JavaScript Jabber? Do you have a burning question for one of our guests? Now, you can join the action at our membership forum. You can sign up at JavaScriptJabber.com/jabber and there, you can join discussions with the regular panelists and our guests.] CHUCK:  Hey everybody and welcome to episode 96 of the JavaScript Jabber Show. This week on our panel, we have AJ O’Neal. AJ:  Yo! Yo! Yo! Yo! Coming at you dead and nearly dying from the bitter cold harsh dry winters of Utah. CHUCK:  [Laughs] I’m Charles Max Wood from DevChat.TV. And this week, we have a special guest and that’s Bart Wood. BART:  Hello. That was quite an intro, AJ. [Laughter] CHUCK:  So, do you want to introduce yourself for us, Bart? BART:  Yeah. So, I went to college, got a degree in Comp Sci in ’03. And I worked for Einaudibleon for seven years, and then Goldman Sachs for a year, and then Henry Schein for the past two and a half years, most recently, basically done program in almost every language out there. Two years ago, I was kind of forced into JavaScript. At first, I didn’t like it, for the first six months or so. But now, I really enjoy it. And I work on a very large scale JavaScript application, a very large single page app, JavaScript on the frontend with Grails on the backend and REST API kind of app. CHUCK:  Interesting. So, on the frontend, are you using a particular framework? BART:  We are. But you wouldn’t really call Backbone a framework. That really is a Backbone, right? There’s not a whole lot going on there. So, when we started this, that was about the only thing around. And so, that’s what we did, but we designed the whole infrastructure over that. It’s got a framework, it doesn’t have a name. But that’s what it’s built on top of. So, it’s Backbone but really, we could port it to most any other framework out there. CHUCK:  Yeah, that makes sense. So, I’m curious. We brought you on to talk about large scale single page applications. Is it really a single page application? BART:  It is. And there is a big distinction. You can have 500,000 lines of JavaScript but if only 30,000 is running in memory and you’re doing full page refreshes between modules, that’s not what I’m talking about. In that type of environment, you can cheat because basically, you’re rebooting the computer every 30 seconds. So, if you can imagine designing an app in C++ where you’re rebooting the application every 30 seconds, there’s all sorts of bad things that you can do and it will never come to light. But this is truly a single page app where all of the code is loaded at one time and then we do a lot of very sophisticated caching and we have browser push from the server to the client. And so, we’ve got a data store in memory and we have to clean up RVUs when we move from one to another. And it really is a single page app. CHUCK:  Huh. BART:  So, yeah. I’m not sure how many people are actually doing this. I remember watching a presentation at Angular, the conference that we had in Utah a couple of weeks ago. And I remember one of the interesting talks that I went in to see was about Google. There’s a guy from Google talking about building massive applications in Angular. And the stacks were something like 70,000, or something like that, lines of code. And that surprised me. I was expecting to see something like 400,000. And so, I’m not sure how far off on the edge this project is. But that’s something that I’d be curious to find out. CHUCK:  I don’t know that that’s something that I can speak to. AJ, do you have ideas on that? AJ:  On apps that are 400,000 lines long? No. CHUCK:  I’m not really sure. I know that Discourse, which is the forum software… BART:  Yeah, yeah. CHUCK:  I know that it’s a fairly large Ember app. But I don’t really know how many lines of JavaScript it is. BART:  Right. That was a pretty impressive app. They obviously have browser push and they’re dealing with large volumes of data. Although their structures are fairly simple, I would guess. But yeah, there’s a lot of issues that you have to deal with especially for a business application where users demand that they are okay if the application takes 20 seconds to start. But once it starts going, they’re going to use it for three hours consecutively and they expect really, really fast performance once it gets going. So, I’m not sure how many other applications really fall into that realm. And so, the issues that we’ve had to deal with like caching, making sure that you use the same domain models, that you’re following an MVC architecture on the client, not throwing away dull moments, and all the performance and stability concerns. I’m not quite sure how much that’s going to be useful for people that are writing like Facebook apps or something like that where their requirements are very, very different. But I can speak to the challenges involved in building this type of application. CHUCK:  Yeah. That would be really interesting to me. I mean, I can imagine that some of the limitations you run into are things like memory. I know that I’ve worked on a couple of apps where we loaded several thousand objects in a memory and it crashed or slowed way down and things like that. I’m not as familiar with some of the limitations that you run into with things like the templates or views or whatever you want to call them. So, maybe you can start talking about those and then you can talk about some of the things that maybe you think would be an issue for an app like this. BART:  Sure. So for memory, early on, I was really, really concerned about how much memory we could actually allocate. And this app runs in anything that has a browser. So as a test, I just started allocating memory in the [inaudible]. On the iPhone, I think it was iPhone 4, I was able to get to about 156MB before the browser crashed. And that kind of blew me away. I didn’t realize that even on the iPhone, you could take so much memory. And on Chrome on a desktop, you can allocate, I stopped counting after about 750MB. I didn’t know we were ever going to even come close to that. But there’s a difference between raw memory allocation and being able to actually traverse those data structures right. And so, we’ll end up caching, I don’t know, probably something like an upper bound of 20,000 data structures. These are just what use Backbone models, I guess, or something like that. The reality is we’ll probably cache something like, I would say 4,000 or 5,000 in an average session. And so, surprisingly, I should have a big caveat there when I say we’re only using Chrome. That’s one of the advantages of doing a business application is we can just tell, [inaudible] for our product, we’ll just use Chrome,” because it can run on anything – iPads or MacBooks or anything. And so, raw allocation, we’re fine there. Being able to traverse the data structures and deal with that, we never really got to the point where we couldn’t do things efficiently if we are careful. But as soon as we get ridiculous amounts of data structures like 40,000 or something like that, just the lookup and the algorithms themselves were turning so badly because they weren’t written to be efficiently that it was the application would bog down long before we ran out of memory. You know what I’m saying there, right? So, you could allocate 150MB just raw just chunking off objects but you can’t really deal with it. And so, the reality was something like, I never really counted but I would guess it would be something like 20MB or something like that. But the difficulty was really managing those models. So, a lot of our developers, they came off dealing what I call mini apps. That’s an application that does full page refreshes when it bounces between modules. But then the module itself downloads all the JavaScript and then it starts pulling in stuff. And MVVM patterns are built around that idea, right? CHUCK:  Yeah. And that’s generally the [inaudible] that I take is if I’m building anything that looks like a single page app, I kind of have a bunch of mini single page apps that are one modular, one area of the overall functionality. So, it’s not technically a single page app. BART:  Right. And do you have ever have data structures that need to be shared between the mini apps? CHUCK:  Yeah. And usually I just wind up having to make it another request to get them back. BART:  Exactly. So, if you didn’t do that then you could imagine how difficult life would be especially let’s say that that application stayed around in memory for three hours. And that data is modified by ten other people in the office potentially. So then, the big deal becomes ‘how do you update with some of the database’ because you can’t have users looking at dirty data. CHUCK:  We did specify on the call. Can you just talk a minute about what the app is and what it does so that people can have some context? BART:  Oh, sure. So, this is a dental application. It’s called an Online Practice Management Solution. Basically, everything that happens in the dentist’s office from large scheduling, patient information, their insurance billing, dental charts, their ledger balances, all that kind of stuff is handled through this application. So, we have a couple of different user types – dentist, hygienist, frontend office people, billing coordinators, office managers and they’re all hitting the same data structures in different parts of the application. And they’ll leave the application open all day long. They don’t really think about, when we say ‘refresh the browser’, they’ll close the browser and reopen it up, right? It’s pretty rare that they’ll actually refresh anything and hit the little circle. And so, they kind of treat it like a normal desktop application. So, when you start — and we can’t really get away with clearing out all the domain models in memory because we’ll have, for example, a schedule that will show 200 patients’ data including all their insurance information, their favorite doctor, all of that stuff, just tons and tons of data. And they’ll want to go to that schedule and they demanded that it happen under a second. [Chuckles] And so, they’ll bounce around that schedule. So, when you go to a week, you have to hold all that stuff in memory because when you come back to it, they expect that the performance is under a second and there’s absolutely no way that you could ever get that having to make all those network requests and fetch the data back in. They’ll accept it the first time that it takes a while, but then the next time they expect it to be almost instantaneous. And so, their demands are quite unreasonable. [Laughs] AJ:  So, what about using PouchDB or one of those other storage mechanisms? Do you do anything with the local caching mechanisms that the browser offers? BART:  No. And honestly, I don’t even know what that is. Does that use local storage? AJ:  It uses IndexedDB or Web SQL. If you’re on iPhone, you get 50MB of Web SQL. And if you’re on Chrome on desktop, I don’t know what the limit is but I expect it’s quite high on IndexedDB. BART:  That would be kind of appealing but it’s kind of also transient. And so, when they do close the browser or when they do refresh, we do want to do hard reload. And so, whatever data that we would store on PouchDB would have to go away. And so, I guess it would be nice because we might be able to query, make a more advance queries. AJ:  Like incremental updates like changes in this time stamp or something? BART:  Well, we do do that. And so, we do have a browser push enabled. So, when any changes they did, the database changes get broadcast out on appropriate channels. And then clients that have loaded data, they check if they have loaded data that has changed and then they’ll have to get the incremental changes. AJ:  So, when you say browser push, are you referring to Socket.IO or are you referring to HTTP 2.0? BART:  Socket.IO. AJ:  Okay. BART:  Yeah. So, that’s a very interesting idea for PouchDB but the truth is that we’d have to probably, is it an object relational model, is it like an object database, like a Mongo is? Or is it a relational database? AJ:  It’s an object database. Well, you can do either one with it. You can actually implement Web SQL on top of IndexedDB. And that’s why they created IndexedDB was because they decided Web SQL wasn’t powerful enough. And since you can implement Web SQL with IndexedDB, it gives you — if you needed to do advanced indexing and stuff on large sets of data, you have actual index trees that you can create and whatnot. BART:  Oh, that’s nice. Yeah, that might be something that we might look into. I doubt it though because the application is so big already. But the truth is that we’ll end up with something like 2,000 patients cached in memory. But the problem is that those data structures are nested sometimes eight levels deep. AJ:  Ah… BART:  Yeah. And so, if you look at the database diagram for this, it actually reflects reality. [Chuckles] And the reality is that the patients’ insurance information and their family relationships and all of that garbage is extremely complex. And so, even in our relational data model, it’s difficult to tease that out, we use Hibernate and GORM, Groovy Object Relational Model, for that which makes life a lot easier. But having to play all those games again on the client would probably not be worth it. And in fact, a major source of pain for our application has been because we need single classes that represent a model like patients. So, we got a class called patient. AJ:  On the JavaScript end, are you actually using classes/prototypical inheritance type stuff or are you just using JSON and operating on that? BART:  No, we’re not using JSON and operating on that because the data structures are really complex and they’re so deeply nested. And they all have business logic associated with them. And so, we don’t use Plain Old JavaScript Objects, we use type classes. AJ:  Awesome. BART:  And one of the reasons why is because browser push notifications from its server to the client. Let’s say that you’ve got a window opened up and I’m looking at a page in it. Or let’s say a more complicated, I’m looking at a schedule and a browser push notification comes up for that patient. I need to find that single model to update to clean up my dirty data. I only use Plain Old JavaScript Objects, I would have to refresh the entire everything. It would be very, very difficult to track down what exactly is going on there. Which of my POJOs is that thing that needs to get updated? AJ:  So, when I think of this situation that you’re describing, the thing that pops into my head is to get everything a UUID. So, regardless whether it’s a person or it’s a transaction or it’s a schedule, everything has a UUID. BART:  Yeah. AJ:  And then if I want to update one, I will just index in to my cache whether it be something like PouchDB or just be in memory and then change that update. And I’m actually kind of not — I don’t know if this good or bad or indifferent but I don’t actually like to use classes very often in JavaScript because I feel like using JSON, like doing it Python style where you’re taking functions and operating on an object. I’ll have an object that’s like users and I’ll call users.whatever and then hand it a user object to do that rather than creating a user instance. But I’m not dealing with necessarily the same kind of stuff that you are. But what do you think about those approaches? Why is that not suitable for your situation? Or what’s the advantage that you have by having classes [inaudible] by nesting things rather than referencing them? BART:  Okay. So, the Plain Old JavaScript Object approach, the POJO approach, is very appealing to me until you get to something large and complex that you need single representations in [inaudible]. So, one of the reasons why some of our nested relationships are actually references the way that you talk about them. So for example, this domain model refers to another root level domain model. So for example, bringing it to the real world, we’ve got a bunch of patient models and then we’ve got a dentist model. We don’t want to replicate dentist everywhere. So, all the patients just reference the same dentist because they all just share them. But then the problem becomes that sometimes you have very complicated data structures underneath like medical alerts that go underneath the patient in their own private patient, but they can be manipulated by their own web services. And so, the problem is that sometimes you don’t always have root level and sometimes you’ll have thousands and thousands of these things across the application. So, it becomes very problematic to put those things at the root of the session at root level domain objects like that you’re talking about because you get a very, very chatty interface. Now, you can do things where you just bulk load and we do a lot of bulk loading and you tease them out until it level objects. But often, when you think about these things in code in a way that you approach them, you program them like they’re one entity even though they’re not. And so, it all depends on the domain, right? So for a lot of domains, you can do what you’re talking about and just have root level POJOs. For example, we started out with this application using Ext JS in Sencha but that model just was not even close to being sufficient for the domain that we’re in. Now, a lot of domains, it will work great like if you’re selling books on the internet. How complicated is that? So, it all depends on what it’s — and also, if you’re not doing a real single page app, if you’re doing a bunch of mini apps, you can do that all day long. It doesn’t really matter. But as soon as you get a single application where you’ve got a lot of complex domain models that are staying in memory for long periods of time and they can get dirty, it’s much more difficult to have everything as a root level domain object with its own [inaudible] unique ID. And a lot of our data models in the database aren’t even modeled like that anyway. For example, a patient has a relationship to emails or addresses. So, patient has multiple addresses. They can have as many addresses as they want to. In that situation, address in the data model is related by patient. I guess that’s actually a bad example. So, let me back up on that one. [Laughs] But after a while, we just realize it just wouldn’t work well with our complicated data structures. I don’t know. Did that make sense at all? AJ:  I mean, I’m seeing stuff in my head and I’m kind of envisioning it. So, I think I’ve got some ideas with what you’re saying. BART:  Okay. CHUCK:  I am a little bit curious. How do you decide when to nest things and when not to? I mean, you have the massively shared resource like the dentist but are there other instances where you decide that, “You know what, we’re not going to nest this under the patient.” BART:  It all depends on — we really just reflect the data model itself. And so, you break up relationships based on references or whether a model is owned by a parent. And you make the distinction based on if that thing weaves or dies with the parent. And so for example, a patient’s addresses, if you kill the patient, you’re going to kill the patient addresses. They don’t belong there anymore. So really, you just reflect what’s actually happening in the data models themselves. CHUCK:  Yeah. Do you have people who are using this in their day to day practice as dentists? BART:  Yeah. CHUCK:  And the next question I have is, so you mentioned that you kind of did a memory test on Chrome and you found that you really didn’t have a limit that you needed to worry about for the desktop. Do you still try and stay under that limit for the mobile devices? BART:  We don’t really have to because we almost never approached past 40MB. And so, we really don’t meter it. We’ve considered doing that and it really wouldn’t be that difficult. What we considered doing is monitoring the memory usage in JavaScript in our session which gives us a rough approximation of how much data we’re caching, which is just normal JavaScript objects. And what we would do is we considered simply the next time you navigate it in the application, to do a hard refresh which would essentially just clear other cache and start from zero. And they would see a hiccup in performance. It would start acting slow again in places where it had been fast and it would take about a minute or two to catch up. We do use Web Workers to un-background load data into the session. So, we fill it up frequently with the data that they’re probably going to be looking at. But that would be the approach that we considered taking. Does that make sense? CHUCK:  Hmm. AJ:  Cool. CHUCK:  I guess the other question I have then is, you talked a bit about cleaning up views and things like that. BART:  Yeah. CHUCK:  If you’re not really doing that for memory reasons, are there performance reasons or other reasons to do that? BART:  Absolutely. That’s one of our biggest things that we have to worry about. There are two types of memory leaks. Just dangling references which are cleaned up by the V8 garbage collector or IE’s or Firefox’s. Or there’s dangling listeners. So, those are the ones that concern us more because those are the ones that cause very, very strange phantom bugs. So, if you have a listener that’s listening on something and the listener is part of something that should have been killed and it continues to get events for whatever, then it will continue sucking up resources in performing calculations. So, we have to be extremely careful when we navigate between views to clean up all the listeners and clean up all of the listeners that are listening to something. When that something goes, we need to clean up. Otherwise, we have zombie views and zombie listeners hanging out everywhere. And that can be a major source of headaches. And so, that was one of our primary concerns with this single page app is cleaning up after ourselves which again, most mini apps don’t really have to care about. They can just [inaudible] and it doesn’t really matter. But for this one, it was a major thing that our framework handles. CHUCK:  So, have you built your own framework then? BART:  Yeah. CHUCK:  On top of that? BART:  Yeah, that’s right. And the other thing that we had to do was we use Chrome’s profiling tools. But unfortunately, I don’t know. Have you guys had much success with the Chrome profiling tools finding memory leaks or performance problems with it? CHUCK:  I haven’t used them much mainly because I don’t go pull those kinds of tools out until I know I have a problem. AJ:  I have played with it a few times. There had been a couple of occasions where I’ve been wondering where stuff is being lost. And it is a little bit tricky because there’s like a sawtooth pattern with the memory. So, it’s difficult to see exactly where something is getting lost, at least the last time I had a problem where I needed to inspect it which was over a year ago. But it was difficult to trace because you see the memory sawtoothing. And so, the way the memory is going up doesn’t necessarily reflect what your app is doing as much as it reflects how the garbage collector is responding to what your app is doing. BART:  Yeah, right. AJ:  And so, getting that one to one correlation was sometimes difficult. BART:  What about for performance concerns? For example, we had a part of our application which is taking about eight seconds to render and this goes along with your question in Skype, AJ. It’s not just the size of the data structures but it’s creating views for them and binding them and all that kind of stuff. So, we had a large schedule view that would take around eight seconds to render because it was creating so many different little views and doing so many things. It was just pathetic. This is one of the views that the users demanded be rendered in under a second. So, have you guys ever done performance profiling with Chrome and had any success with that? AJ:  Well, I have used the Chrome tools. But usually when there’s a problem like that, it’s in the DOM and it’s fairly obvious. BART:  Ah. AJ:  It’s like I’m rendering a list of a thousand items and I really only need to view ten of them, but before I was just playing around and using a small dataset and then when I put in the real data, all of a sudden it gets slow. But it’s not like, “Oh, I wonder where this is happening.” It’s like, “Oh, I know that that list could be a list of a thousand and I know that I really only want to show ten and that the other thousand that are being rendered on the page are useless to me right now. So, I need to go make sure I limit that list and only display the items that I actually am interested in viewing at the time that I’m rendering them. BART:  Right, right. Yeah, that makes sense. A lot of our performance problems were exposed when the datasets obviously got bigger, right? But unfortunately, our problems weren’t that easy to discover. For example, some of our problems were from zombie views that weren’t getting closed up that were sucking up resources, that were getting triggered events, recalculations, resizing, position, that kind of stuff, or whatever. So I found that also often the Chrome profiling tools, it wouldn’t tell me what functions actually were slow. It would give me some gobbledygook which I couldn’t translate to actually my own functions. And maybe it’s because we never actually name our functions but we always have our references to them. I’m not quite sure. But I ended up having to write a tool called Kojak that basically wraps the entire application and just does pre-imposed calculations and it’s able to figure out where it is in the stack frames and all that kind of stuff. So, essentially I didn’t want to. I’d struggled with Chrome for about a month trying to get it. No, probably about two weeks, trying to get it to give me the information that I wanted. But finally, we had to write a tool to do this for us and it’s open sourced. It’s only got about a 130-something watchers on it. But basically, after about using that for about an hour, we were able to pinpoint some memory leaks that we had and some functions that were getting called hundreds of thousands of times when they should have only been called a couple hundred times. And so, we were able to go through and figure out what was going on pretty quickly with that. AJ:  So, the last time that I used the developer tools to find functions that were being slow, the thing I was actually doing was image manipulation. And this was when it wasn’t as good as it is now, the Canvas API and the new image manipulation tools that are part of JavaScript. And I definitely know that if you can avoid anonymous functions, it’s going to help you to be able to debug stuff. And the experience that I had with the Chrome tools was it helped me where I needed the help. And I assume that they’re much different now, which could be better or worse. I know that every couple of weeks, I get an update when I open up the developer console. The buttons are moved to the left or to the right or to the bottom or now there’s a new panel and all that kind of stuff. But the one time that I had a crazy slowness problem was I was going over a million pixels or however big the image was, and doing some operation on the color. And the thing that was slow was actually one of those weird things that you’d think would only happen in C where I ended up switching it from a multiplication to a plus equals. And it made all the difference. And it went from taking eight seconds to do the operation to taking 0.3 seconds. BART:  Oh, wow. Nice. Yeah, even my profiler doesn’t handle anonymous functions at all. It’s kind of impossible to go and figure out where they are. If you define a function inside of another function and it’s not referenced anywhere besides internally in the closure, even mine doesn’t even handle that either. Pretty hard to get information from that. AJ:  So, explain a little bit more how your tool is working. You said it wraps it? BART:  It’s quite simple. All it does is it goes through the root of the application and it finds every single function that it can recursively and it just wraps it with another function. And in the beginning of the function and in the end of the function, it just simply takes timestamps. And then it’s able to figure out where it is in the call stack, so which functions took to call it before getting into that function. And then each function itself remembers its call stack and how to get into it and how much time it took and how many times it was called, all that kind of stuff. And so, yeah? AJ:  Is this a parser, like Emscripten or I think that’s the name of it, where you’re traversing the tree as a parse tree and performing these manipulations? BART:  No, it’s more simple-minded than that. And really, it’s limited because if you’re using something like RequireJS to hide your modules, this tool will not work unless you expose your modules to this tool with a shim. And so, the tool is pretty simple-minded. It just goes through whatever root namespaces you chose. And it will go through all the objects which it treats like packages and just iterates down through them and just wraps everything. AJ:  Oh, okay. So, this is kind of calling object.keys. So, this is a runtime tool? BART:  Oh yeah, yes, yeah. And that’s why I couldn’t get it working with Ember. I only spent about three hours on it. But Ember does everything so dynamically that it’s almost impossible to get everything in memory to be able to profile it. AJ:  Right. BART:  That’s right. So, you can use it with Angular with a shim or RequireJS with a shim, or if you’re just doing a normal application with namespaces that don’t hide the modules, it’s trivial right? The tool itself is actually really simple. I kind of wish that somebody else had written it. But it’s extremely valuable because you can see the functions that you want to see and weed out all the garbage. So I don’t care if string.replace was called a bajillion times and it took this much time, right? I only care about my own functions that I wrote. And so that’s one nice thing that the old-school profilers would give you, like Rational Quantify or something like that. They would actually let you weed out all the noise and only concentrate on your own code. But you’re right. It has to be loaded in memory initially or it has nothing to do. AJ:  Alright, cool. CHUCK:  So, are there any other areas of concern when you have a long-lived single-page app that we haven’t asked about? BART:  No. I mean, if I had my preference, I probably wouldn’t build them because they’re just riddled with danger. [Chuckles] CHUCK:  So, I guess that leads to another question then. Why would you do that in this instance? Or would you go back and do it differently? BART:  Now, unfortunately it has to be this way for the users demanding performance concerns. That’s about the only way to do it. So if you want to be able to load and cache data and be able to render views really, really quickly, that have a ton of data, you might be able to mitigate things by clearing out the cache more, or something like that. I doubt it though. But once you have lots and lots of data structures that can all change and that the users want to render very, very quickly, that’s about the only way to do it. But it’s very tricky to do and it requires a whole lot of unit tests and functional tests. Because as you guys know, JavaScript will happily take anything that you give it and try to make the best out of it and not warn you about anything. Right? It’s one of the nice things about the language, is it’s so flexible. But it’s also so dangerous because often you can have bugs in your application and not see them until you actually look at what’s happening on the screen or whatever. Yeah, I guess you could [inaudible]. But definitely, I would prefer to writing mini-apps and using Plain Old JavaScript Objects in memory to having data stores. But it all depends on what your users are demanding. It’s possible to write them, to write single-page apps that are very performant. It’s just you have to be very, very careful in how you design them. And the truth is that you can have large single-page apps that maybe don’t require, the data structures aren’t that complicated. Or in some situations, it doesn’t make sense to cache all the data. For example, we have financial widgets that go across the entire, in some cases, large swaths of the database to do financial calculations. And that data is very, very impractical to cache on the client for a lot of reasons. Sometimes security, sometimes it’s just too much data to cache. And so, all of that stuff, all that logic, really goes on the server. And in that situation we don’t really use Plain Old JavaScript Objects. I mean, we don’t use the session with data models cached in it. First of all, because the actual data is pretty small. They’re financial reports which are just a bunch of numbers. And the user is a little bit more forgiving for these reports to be slightly slower and all the data to be calculated on the server. And that’s a little bit different than loading all of the data, all of the patients and clinical and doctor information and addresses and insurance and insurance carriers and all that other garbage. So, not all single-page apps have to follow this model, right? It’s probably something like, I don’t know what number. But if they do, then they have to be concerned with all these issues, specifically nested models. Probably the biggest gotchas were nested models, pushing data from the server to the client, and being able to find single representations of the models to update, and having the views update if they’re looking at that data initially. And so, those are probably the biggest hurdles that we had to overcome. And we would have had to overcome these in Ember or Backbone or Angular or anything. They’re pervasive across any application like that. AJ:  You didn’t mention React. BART:  Oh. Well, React looks pretty cool. But I haven’t tried it yet. You guys play around with that at all? AJ:  I haven’t but I saw a presentation on it at one of the Utah JS meetings. And then we did have somebody on the show about React earlier. And if I’m not mistaken, it looked like it may actually serve well in the kind of environment that I’m envisioning from what you’ve described. Because I think React does a lot of stringifying instead of DOM manipulation, so it will, if I understood the demos correctly, it takes the strings for the DOM, concatenates them all together with some simple replace templating type deal, and then inserts into the DOM afterwards, once it’s constructed the objects at the level that it needs to. So, if I remember correctly about what I was told, it basically reconstructs the whole entire thing with just the pieces that are changing. So, if a component hasn’t changed, it uses the same thing it used before and then puts it together at once. Chuck, do you remember? Am I explaining that correctly? Or am I off? CHUCK:  I haven’t really played with it. But I do remember that in the episode that we did on it, yeah they talked about how they have a virtual DOM object that they compile all the changes into and stuff like that. I don’t remember all of the details. It’s been a little while. BART:  Yeah, actually I was reading their documentation about a month ago. And I only spent an hour on it. But what I read, it looked really exciting. And from what I recall, one of the things that they were doing was they seem to not have their templates have too much logic in them, which I’m a huge fan of. But yeah, I’ll be attending Fluent pretty soon here. And I hope to learn more about React. It looks pretty cool. So, one of the downsides of such a large application unfortunately is that when all these cool new things come up, we’re kind of stuck with 200,000 lines of code. [Chuckles] And so, it’s just got to keep going on with whatever it is. AJ:  Yup. CHUCK:  Yeah, that’s true. BART:  Yeah. CHUCK:  So, do you find that it’s hard to keep track of all of the stuff that goes on in that app with something that large? BART:  [Chuckles] Yeah. Yeah, so I’m the architect on the project and we have something like, I don’t know, 30 developers. But we try to use Confluence a lot and we try to rely on unit tests and code coverage metrics, that kind of stuff. But we use, sorry not Confluence, we use Crucible for code reviews. And so we try to make sure that we have some quality with the code reviews. But still it’s very challenging. CHUCK:  Cool. Well, it’s been really, really fun to talk to you. And hopefully, this will help people figure out some of the things that they need to consider if they’re heading toward a large single-page app. We’re going to go ahead and get to the picks and start wrapping up the show. But like I said before, thanks again for coming. AJ, do you want to start us off with the picks? AJ:  Sure. So recently, I saw The Book Thief and it was a very interesting movie. I had no idea of anything about it. I just heard people say it was good. And I didn’t have a synopsis or anything. And some friends were like, “Hey, do you want to go? See it at the cheap seats?” and I was like, “Yeah, let’s do it.” But it’s about Nazi Germany, but not about the concentration camps. Just the world war lifestyle and following the story of this young girl and her growing up in this environment where she was taken from her parents. And usually, I don’t get emotional with movies that I know are fictional, even if they’re historical fiction, because I just have this mental block where unless something is closely based on a true story I just don’t allow myself to get involved or attached. But it was very provocative for me. It caused me to think and put myself into this alternate reality. And it was rather touching at some parts. And that’s all I have to pick this week. CHUCK:  Alright. I’ve got just one pick this week and that is Focus@Will. It is a service. It effectively just plays music, but the music, it’s not the kind of music that I would listen to just out in the car or whatever. But in fact, you can click on the science pace and it will actually explain all the neuroscience and all that stuff behind why they choose that type of music and what it’s supposed to do. But basically, it shuts down certain parts of your brain so that you’re not as distracted. I guess it just quiets the voices, so to speak. And then it allows you to really focus. I’ve only tried it. I tried it yesterday because that’s when I found out about it. And so far, I really like it. Now I’m not a neuroscientist. This is the, I’m not a lawyer, or not a health professional, and not an expert. But whether or not it has sound scientific backing, I can’t say. But it seems to be working for me. So I like it. And I’ll put a link to that in the show notes. Bart, do you have some picks for us? BART:  Sure. ‘The Way of Kings’ by Brandon Sanderson, like every good nerd programmer out there, I love sci-fi and adventure books. This is one of the best that I’ve ever read. Quite a good book. And then Vikings season 2 is coming up in March. So, one of my favorite shows on TV. CHUCK:  Awesome. AJ:  Oh, I want to pick one other thing. So music, there’s this track called Relativity by Faded Paper Figures. And I would classify it as so indie it hurts. It’s like a mix between The Fratellis and The Postal Service, which are two bands that you would never really consider mixing together. Or at least, that’s how they appear to me. But it was really, really fun to listen to. A friend shared it with me. I have no idea what the release date is on it or when it came out. I don’t know nothing about it except for I got shared a Spotify link and it was awesome. BART:  Cool. Well, I hope this wasn’t too broad and generic for your audience. I’ve listened to your other things and they’re usually pretty in-depth technically. This is kind of a broad strokes, so hopefully somebody can actually get some usefulness out of this. Hard to go into details though with something like this. AJ:  Well, I liked it. BART:  Oh, okay. CHUCK:  I did too. And one other thing is that we invite all of our guests to the JavaScript Jabber forum. And so if you have specific questions for Bart, hopefully he’ll join up and you can ask them in the forum. And you can sign up there for that at JavaScriptJabber.com/Jabber. And then if there are other, are there other good ways to reach you, or if people have questions, to find out more about this stuff? BART:  Yeah, my GitHub site. I chose my name without realizing I would actually care about it someday. It’s TheIronCook. So GitHub.com/TheIronCook. And you can just post issues or really anything there. You can check out my two open source projects there. Or Twitter, I’m SBartWood. So, it’s like Steven, SBartWood. CHUCK:  Yeah, and one other thing that I’m sure we’re going to get asked. We’re not related. [Chuckles] BART:  No. But you know what’s funny? I’ve got a son named Charles. So, we’re close. CHUCK:  Oh, good. [Chuckles] Alright. Well, we’ll go ahead and wrap up the show. Thanks for coming again, Bart. BART:  Yeah, thank you guys. CHUCK:  We’ll catch you all next week.