041 JSJ Single Page Applications

by woody2shoes on January 4, 2013

Panel

Discussion

02:09 – Follow Up to 040 JSJ Conferences

05:28 – Single Page Application Frameworks

15:10 – Path & Hash Routing

22:23 – Synchronizing Your Data

24:51 – WebSockets

32:44 – App Issues

  • Memory

38:52 – When do you want a Single Page App?

Picks

Book Club

Transcript

AJ:  Yeah, I think I’m 26 still, for another 6 months.

CHUCK:  Yeah. You have to count on your toes to figure it out.

AJ:  Yeah, twice actually. Because once I’m already bent over, I just keep counting on my toes. I don’t start back at my fingers.

CHUCK:  [laughs]

[Hosting and bandwidth provided by the Blue Box Group. Check them out at Bluebox.net.]

[This episode is sponsored by Component One, makers of Widge Mo. If you need stunning UI elements or awesome graphs and charts, then go to WidgeMo.com and check them out.]

CHUCK:  Hey everybody and welcome to Episode 41 of the JavaScript Jabbers show. I almost said Ruby Rogues. How tired am I?

JAMISON:  Don’t cheat on us, Chuck.

CHUCK:  It’s right after Christmas.

JAMISON:  We know you have another family but we love you when we have you.

CHUCK:  Oh, my gosh! Yeah, we had family here for two days and my wife panics when people are coming over and has to have the house immaculate. And then she kept getting tired or sick or having some other issues. So, I kept forcing her to go to bed and then staying up until 2:00 AM, cleaning the house. So, I’m totally worn out.

Anyway, so this is JavaScript Jabber, it’s not Ruby Rogues. If you want Ruby Rogues, go to RubyRogues.com and see what we were talking about over there.

Last week, we talked about conferences and I know that AJ wanted to say something. I guess we usually do the introductions first. So, let’s do that and then let AJ say his piece and then we’ll move onto our topic for today.

So, this week on our panel, we have Jamison Dance.

JAMISON:  Hi, guys! Merry Belated Christmas.

CHUCK:  We have AJ O’Neil.

AJ:  Yo! Yo! Yo!  Coming at you from the green Christmasphere of Virginia.

CHUCK:  Oh, you’re in Virginia?

AJ:  Yes, I am. Visiting family.

CHUCK:  Cool. And I’m Charles Max Wood from DevChat.tv. I just want to put a quick plug in for my Rails course. If you want to learn Ruby on Rails, go to RailsRampUp.com. It’s kind of a guided course and you get a lot of access to me to learn it.

So AJ, what was it that you wanted to chime in with, with the conferences that we couldn’t get you in last week to say?

AJ:  Okay. So, both Merrick and myself have had this same experience. So, we were talking about having the broad conference versus the focused conference, the broad talk or workshop versus the more focused one. And we both have come to the conclusions that having it more focused is better. With the conference, it’s fun to go to a broad conference but even in that, like it’s nice to have the focused talks like the ‘Utah Open Source Conference’ which this year is ‘Open West Conference’. It’s expanding out and they’ve got some big surprise. I’m guessing they got some nice speakers. And the call for papers for that opens on January 2nd supposedly. So, that’s a really nice conference but it’s broad but it’s still fun.

But the focused conferences and the focused talks are so much easier to give a focused presentation because you have a better idea of what the people’s background is. Like the talk that I gave on JavaScript at ‘Utah JS’ went so much better than the one at ‘Utah Open Source’ because there were Python guys, there were guys who are noobs in that community. So, it definitely didn’t flow as well as when I was surrounded by JavaScript people that all had some experience in JavaScript.

CHUCK:  Yeah. That makes sense. I mean, for me, the nice thing about the big conferences is that there are more people to interact with.

AJ:  Yeah.

CHUCK:  The smaller conferences and usually more focused conferences, you definitely get that vibe and I totally get that. So yeah, I happen to agree. Is there anything you want to add to that Jamison before we move on to the topic for today?

JAMISON:  I think the ideal model would be is you could get exposed to a broad group of people because there’s value in when you bring in people that aren’t super familiar with what you’re talking about but are experts in some other domain, they look at problems in a lot different way. So, I think there is some value in smart people that aren’t experts in what you’re talking about but if you can also combine that with — I don’t know, maybe there’s some way to say, “Come to this if you’re a JavaScript guy because I’m going to go in-depth on stuff.” Or, “Come to this if you’re a Python guy.” And then maybe have some broader talks as well, then you can kind of get the best of both worlds.

CHUCK:  Yeah. I think part of the thing is that it’s definitely easier to tailor your topic if you’re giving a talk if you know that it’s got this narrow focus. But that doesn’t mean that you can’t do that if you’re speaking at a conference. Yeah, the people who want to go in-depth on that topic can go to your talk even if it’s a broader conference. With the narrowly focused conferences, the nice thing is that you know that most of the talks would be catered to you if you’re in the demographic that kind of fits what that one is after. But yeah, I agree with you on that too.

JAMISON:  Yeah.

CHUCK:  Well, let’s get into this week’s topic. This week, we’re going to be talking about single page applications. I don’t know how many single page applications you guys have built? I can honestly say that I have built a grand total of no single page applications.

JAMISON:  We won’t tell a soul.

CHUCK:  [laughs]I have to say, some of the applications I’ve built, I’ve had workflows that were sort of a single page application, but they were a subset of the side like the whole thing wasn’t all one application. It was kind of like three or four applications that were all connected so they kind of lived in the same over arching app. I don’t know if that counts or not.

How about you AJ, how many of these have you been involved in?

AJ:  A few. When I first got into JavaScript, back, I don’t know maybe four or five years ago-ish, one of the first things I tried to do was I realized, “Oh, I don’t actually have to have multiple pages when I’ve got jQuery. I can just get the data with JSON. So, I kind of went on it straight away. I won’t say that it’s architected really well. There’s definitely some architecture concerns. Like if you’re lazy, it’s a lot easier, I think, to do it with multi-pages.

To answer the question, things that have actually been public, that people have seen, I’ve probably done four pretty small apps that are single page.

CHUCK:  How about you, Jamison?

JAMISON:  The thing I’ve been working on for the past like eight months is just a big single page app. So, I haven’t done a ton but I’ve gone pretty in-depth with this one.

CHUCK:  That’s the project for i.TV?

JAMISON:  That’s Nintendo TV. We use like the TV guide thing?

CHUCK:  Oh, cool.

JAMISON:  Yep.

CHUCK:  So, with a lot of these single page apps, it seems like, you know, I guess you could do it with jQuery like AJ said. But it seems that there are a lot of frameworks out there that make it a lot easier. Which frameworks have you guys been using for these?

JAMISON:  In production, we use Backbone. I’ve actually thought a lot about this about why Backbone is such a good fit for us because we have had to build a lot of abstractions on top of it, and some other frameworks come with more abstractions out of the box. But we have kind of a weird app in that it’s single page and it’s responsive and feels more like an application.

But it has very little data entry. There’s not very many places where the user can manipulate data in the app. They can just kind of change state, like where they are in it but they can’t really put in that much new data. So Backbone is a great fit for that because we just get all our data from the server and render it on the page. And then, when they want to go to somewhere else in the app, we just have to get more data from the server and render it. We don’t have to worry about keeping stuff in sync or re-rendering lots of things as users like click buttons or enter form fields or something like that.

CHUCK:  Yeah, that’s one thing that kind of strikes me as an issue. I know that Ember.js handles a lot of that itself where if you are munging through a lot of data when you go and get another copy of the same object, if it’s changed, it gets updated everywhere.

JAMISON:  Yeah. Ember has its tough things but the one thing that I’ve found it’s the best at is just keeping your page in sync with your data. It does that really well, and like all its tools and abstractions are really focused on making that happen. So, it’s amazing at that.

CHUCK:  Yeah. Jamison or AJ, have you done a whole lot with kind of the data synchronization issues?

AJ:  Not really. I’m not too worried about the DOM stuff. I normally just have a render function that I call. The template engine that I’ve used a lot is called Pure.js. I’ve mentioned that before. I’m kind of interested in looking in the one that Merrick was talking about, Plates. And then, for really small things, I just use jQuery and call the .Text to pass something in.

And I’m interested in checking out Angular. I haven’t done it yet but now, that I’ve gone Indie, independent consulting, I’ve got a little more time on my hands, I think I’ll take a look at that one because it seems the most promising.

JAMISON:  So, just rolling your own render function works great if you don’t have lots of nested things to render. But if you have tons and tons of nested views and you’re just rolling — I’m using Backbone terminology already. But if you have lots of things that you have nested inside each other, I imagine then your render function will call render functions on sub things you have nested. And if you just do it all yourself naively, then little changes at the top level will cause your entire page to re-render. And that’s fine if you don’t have lots of stuff. But if you have lots of things, then you need either to think more about your templating system or use some framework that takes care of that stuff for you.

CHUCK:  It seems like for a lot of this, you could roll your own with some kind of an event. And then every time you render a new element that sort of binds to your data collection, then you bind it to the change event for each element or for the collection as a whole just so that it can update itself. That way, you don’t have to think too much about it, other than saying, “Oh, we got something and yes, it’s different.”  So, fire that change event and then let it kind of trickle through the entire page. And having something that won’t miss elements and that will update everything properly seems like a good way to go. And so, some of these frameworks really do that really well.

One other thing that really comes to mind for a lot of this is, it seems that a lot of the different pages that I build, when I’m building things that go to different pages for different jobs, it seems like doing a single page application might be overkill for that if the layout is drastically different and things like that?

JAMISON:  What do you mean?

CHUCK:  So like I have, let’s say I was building some kind of scheduler app. The example that I keep coming back to for the Uber application that I want to build some day is the Dental Practice Management application. And so, if I built just a single page app, there are some benefits with performance and things and you already have the data and so you can just update the layout on the fly. But do you just throw away the old layout? And then put the new layout in when you “change pages” or do you just hide one and show the other? How do you usually manage that?

JAMISON:  I think usually you just destroy — so you clear out or destroy the DOM elements then just render new ones.

CHUCK:  And do you just do that off of whatever templating engine you’ve decided to use?

JAMISON:  Yeah, I mean so the way we do it on our app is we have a destroy function on all of our views, and when the views get cleaned out, they call destroy and destroy you can override it to [Inaudible 13:03] or do any kind of — say you’re models are doing some weird things, pulling or something then you have to turn that off.

But then you also just remove the element from the DOM. So as you destroy the parent view, it will just call destroy on all the child views and remove all the DOM elements and then a new one gets created and inserted into the DOM in its place.

AJ:  So, why destroy rather than just hide?

JAMISON:  I guess to have less stuff cluttering up the DOM. We have…

CHUCK:  Well, there’s the DOM being cluttered this one thing, also memory.

JAMISON:  That’s all part of it, it’s a resource issue. I guess you could just cache you’re entire app every time they go somewhere? Check in the cache if you’ve already rendered that view and just grab it from there. But that cache could get very big. There are some limitations on the device we’re running on that make that. And you could do that on a desktop, like web app but it’s a little bit tough to fit all that stuff in memory on the environment we’re running in.

CHUCK:  So just to be clear. Some of the things that you have to worry about if your framework doesn’t handle this for you, and we have to kind of wave our hands at that because all the different frameworks are really good at different things. So, some of them will have something that does this and some of them won’t.

So, you clear the DOM. You clear all of the event handlers or all the event registrations or whatever they, for those elements so that it doesn’t worry about watching for those anymore. Then you also have to clear out the objects that you have in memory related to the old layout unless they’re being used by the new layout.

JAMISON:  Yeah. We don’t really have to do very much at all with the actual memory management stuff. We had a couple interesting bugs but that seems to happen pretty well automatically with the garbage collector. Unless you’re like storing all of your models in some global state, I don’t know. That should happen automatically unless you’re doing something crazy.

CHUCK:  One other thing that comes to mind is the path. So, a lot of times you see the hash bang or something in the path in order to get — you are effectively changing state instead of changing pages.

How frequently do you do that kind of thing versus just updating the page with whatever you want? Because it seems like the hash state or the hash bang or whatever is just there so that if somebody comes back to your application, they can load the state they were in rather than having to navigate to wherever that was.

JAMISON:  Yeah. I don’t know if there’s a super hard and fast rule on that besides just, do you want the user to just be able to go directly to this state? And if so, give it a unique URL.

AJ:  I want to talk to that just a little bit. I think the principles arrest can be applied just as well on the client’s side, as they can on the server side. And one thing that’s kind of difficult about doing it is that — so we have these systems where a JavaScript has become really modular but HTML and CSS have not yet really seen that kind of thing. Like, if I ‘NPM install’ something that I want to use with a browser package manager and I require it, then it all gets concatenated into the one file and everything. But if I do an include from my Jade template or a Mustache template, then that doesn’t necessarily include it from the NPM module and stuff like that.

JAMISON:  So you’re saying ‘modular’ in the way that you could some magic command install and it will install the JavaScript, and the CSS, and the HTML to use it? Some widget? 

AJ:  Yes. So, I’m going to hone in back to the routing issue. But I think the larger issue is that the community as a whole has not yet recognized that we can throw the HTML, or Jade, or Mustache templates in with the NPM module and provide a way to require that. So this idea of widgetizing the components of a page hasn’t really gotten hold in the minds with the masses yet.

So with the routing, if you design it well, you could route to a widget. And then give parameters to that widget in the same way that you do like in Sinatra or Rails or Connect or whatever where you have something that you kind of mount on. You say everything that goes to /widget name. Like for example, /users gets handled with this code. And then whether it’s a post or Git or yada…yada…and what parameters yada…yada…, it behaves differently.

So with the hashes or BAU, the transition to using PushState or PopState where you don’t have to use the hash, you can just use the slashes without the hash sign. You can do that same thing. You can architect your app so that you route your code to functions that activate particular widgets. And like we use cookies for the server communication, you can use local storage for the client inner communication with itself. So if you wanted to do a post, you could attach it to an object or you could put it in local storage since you don’t have a post body but you can still follow those same semantics just with a different mechanism. Does that make sense?

CHUCK:  So basically what you’re saying is you can use your hash notation not just to say, “Go to this particular state.” But you can say, “Go to this particular state and maybe you’ll have some components in the sidebar,” that you’ve put other things into that hash path or hash information that says, “”Oh, by the way, make the sidebars look like this and make this look like this.” And so, you can give more information than just one particular state but you can trickle down to the state of other things on the page and change the way that they behave as well?

AJ:  Yeah. And there was Sammy.js and I think it was called jQuery.bbq that they used to do that when the hashes were popular. But now, everybody is transitioning over to PushState and PopState. I don’t know if those libraries have been updated to handle that as well.

CHUCK:  PushState and PopState, is that the History.js that we talked about a little while ago.

AJ:  Yeah.

CHUCK:  The stuff that it handles anyway.

AJ:  Like when you’re on BlogSpot and you click on someone’s blog article and it doesn’t refresh the page, it just opens up the article bigger and moves the other stuff out of the way but it gives you a different link up at the top.

CHUCK:  Yeah.

AJ:  So it’s just that it replaces what’s in the URL bar without contacting the server.

CHUCK:  Yeah. That’s a pretty common thing. I think we’ve seen that in a lot of areas where it just updates the top bar without actually sending you to another page. And that’s what we’re talking about with the single page applications. But that hash thing is kind of a placeholder that says, “Here’s the state we’re in at the time,” without actually forcing you to save stuff into the browser itself because if you close the browser or in certain cases, if you close the tab on the browser, then it dumps everything it has in memory. So if you go back to that link, you need that to have enough information to say, “This is how the page was put together when they left.”

And so, what you’re saying is if they had changed the state so that it wasn’t just showing a particular blog post but it was showing a blog post and showing several different components in different states, that it carries all that information so that you can basically be back where you were. You just don’t have the history at that point.

JAMISON:  That’s something that Ember explicitly tries to handle as well. With their router is more like a state machine than just a traditional router. You can have nested routes that are still on the same main page, like you were saying, but changing components within the page and stuff will update your URL so that you can easily just completely reconstruct the page from the URL.

CHUCK:  Yeah. So then, what it comes down to is, do you need something like that or not?

JAMISON:  Yeah.

CHUCK:  Because I can definitely see some simple applications that it’s just like, “Well gee, that’s real nice to have but it’s a tool in the toolbox that I’m never going to touch.”

JAMISON:  Sure.

CHUCK:  So, it just depends on whether or not you care. And sometimes you do, sometimes you don’t. Sometimes you can get away with it on a larger app. And then others, you’ll have power users that really want that functionality.

JAMISON:  So one thing we haven’t talked about a ton that I think would be important to talk about is synchronizing your data. We mentioned just Ajax and that’s kind of the basic case. But what about if you need to keep things in sync when other things could be changing the data in the background? So, you’re showing something like shared view that lots of users can edit data on. How do you make sure that stays in sync?

CHUCK:  We talked about like keeping the DOM in sync with the data a little bit with the events and trickle downs and all that stuff. And then, this component stuff kind of ties into that too. One thing that comes to mind here is something that Rails does with all of its models and that is that it adds a ‘created at’ and an ‘updated at’ timestamp. And so, if you have that or some kind of versioning mechanism or something, then you can just compare the version numbers. And then every time you do a request, you just cycle through them and see if you already have them and if they’ve changed. But I don’t know how efficient it would be to actually do something like that?

AJ:  If you want to do it live, you could use WebSockets and then I think the timestamp idea works pretty well. If there’s two updates, you just take whichever one made it across both boundaries is the one that wins and you just play that one.

JAMISON:  Yeah. I mean, if you really care about keeping all updates, you can look into, I think it’s operational transformation. There’s this whole field of research on doing simultaneous updates to the same text and merging them together.

CHUCK:  That’s interesting. I don’t know that we have any objects that really carry that kind of data unless it’s like a huge blog post or something; that much data, anyway.

JAMISON:  The classic one is, have you ever used Lucidchart?

CHUCK:  No.

JAMISON:  It’s just this online charting thing. It’s basically — what’s the Microsoft one? Visio? It’s pretty ridiculous. They’ve re-implemented lots of features in Canvas. So everything is really responsive and works pretty much like a desktop application.

AJ:  That is way cool.

JAMISON:  Yeah. It’s amazing as just an example of a web app. But they do lots of this OT stuff to merge in changes if you’re editing the same diagram at the same time. So it definitely can be useful in certain situations.

I know about WebSockets. I haven’t used them in production a little bit. Not a little bit, at all. So do you want to talk a little bit more about have you deployed them or used them in something, AJ?

AJ:  Have they gone into production? I don’t think I’ve used them in anything that was really in production but I’ve used them in a couple test apps.

JAMISON:  So, I guess I should just back up. We do stuff with keeping data in sync. Data can change from lots of different backend sources in our app. But we just do lots of polling and it works fine for us. It’s not ideal that it adds some latency obviously when whatever a polling interval is because that’s the fastest you can get updates.

CHUCK:  Polling has worked well for the web for 20-odd years. I would expect that it would work for you. But yeah, there are some trade-offs.

JAMISON:  Yeah. We’ve looked at WebSockets and we’ve used them in other apps, not in this one. But it seems a little bit scary trying to — it seems like it would be a lot more resource intensive, like with polling, caching all works fine and there’s lots of tried and true techniques for just HTTP requests that all work.

AJ:  And so, I think that’s kind of the down side of WebSockets is that it’s not something that you can curl. Like, when I think about architecting a web app, I kind of start with, “How do I curl it?” I’m not as worried about…

CHUCK:  [crosstalk] initiated when he says ‘curl’, he means the curl utility in the Unix or Linux world that goes and does a request to a web server and gets a response back.

AJ:  Yeah. So it’s like when you aren’t dealing with a test framework yet and you just want something quick and dirty, curl is what you use. And if you go to api.yourfavoritewebapp.com, it’s going to give you a bunch of stuff with curl examples on there or at least in a lot of cases. Like the joyant website, if you do api.joyant.com, I believe. That takes you to a page where they have a bunch of curl stuff. At least it used to.

So WebSockets are kind of new. And so, there’s not like a standard utility like NetCat or Curl where you say, “WebSocket, connect to this and let me debug it by hand.”

CHUCK:  Yeah. The best thing you have for that really is you build your application with some kind of end point that will make the connection for you with JavaScript and then you fiddle with it over the console.

AJ:  Yeah.

CHUCK:  And you fiddle with the back end sending information over the WebSocket with another console on the server.

AJ:  So, I think the case for the WebSocket is more just streaming data that is changing frequently and that isn’t super critical to save and archive. Maybe you’re saving and archiving it but it’s not like a document or a file. It’s like a stream of text or something. Yeah like a chat server or if you are moving something around on a page and you want to move those updates quickly like a game or something. That would make a lot of sense, I think.

CHUCK:  Yeah, where you basically need the immediate feedback.

JAMISON:  It’s basically when you want the page to react to the data change immediately.

CHUCK:  Yeah. And then you just manage it using some of the mechanisms that we talked about or find a framework that will do it all for you to keep it all in sync and update everything the way that it needs to be updated.

AJ:  Yeah, because if you just one timely use WebSockets, I think that you end up with the TCP problem again. It’s, kind of, could be a step backwards for you. It’s like people that don’t understand HTTP, they try to implement things in TCP. And they’re like, “Oh, I need a way to specify a resource.” And, “Oh, I need a way to specify compression.”  And, “Oh, I need a way to specify encryption.”  And, “Oh, I need a way to say what the content type is and what the byte length is.”  And then when they’re done, they spent three months designing some protocol that is known as HTTP by everyone else except their version isn’t compliant with anyone else’s.

[laughter]

AJ:  So I think with WebSockets, there’s definitely a temptation that you could architect things poorly and then end up just having done better using regular HTTP.

CHUCK:  There have been issues with WebSockets in the past that I think most of them have been solved – the security issues and some of the other issues that have come up with it. The only other problem that I really see with it is that it’s not a strong standard in the sense that if you build an HTML page, any browser you deal with is going to be able to render it pretty close to accurate.

If you’re using WebSockets, some of the web browsers out there support them in different ways. And so, you can’t always count on more than just the really, really basic features of WebSockets working in the browser that you choose.

AJ:  And I would like to clarify that by some, we’re not talking about Internet Explorer 6.0 in this case. It’s actually legitimate like mobile browsers are different, versus desktop browsers, versus the version of WebKit that Safari uses, versus the WebKit that Chrome uses.

CHUCK:  And then the other thing is that a  lot of the older browsers don’t support them.

JAMISON:  Some of that can be abstracted away if you use one of the WebSocket libraries. Socket.IO is one. It depends on some backend components as well. I’m not aware of any other ones but I’m sure there are more WebSocket libraries out there that will fall back to long polling if they need to or some other things, if WebSockets isn’t supported in the browser.

AJ:  Have you used Web, I mean, Socket.IO?

JAMISON:  Oh, I’ve used Web. Yes.

AJ:  No, no. Socket.IO.

JAMISON:  I have used Socket.IO, not in production. I’ve done a couple of just little tests with it but I have no experience with scaling it or making sure it stays up or anything like that. I’m not super experienced with it. It’s something I need to look into more.

AJ:  I played with it but I’d like to try doing raw WebSockets a little bit more because when I did try Socket.IO, granted it was a long time ago, I think things are much improved. But it kind of got a little bit confused between the long polling and between different browsers. The experience of the stability of it was not consistent. But that was like a year ago when the standard was still changing, now the standards pretty much finalized.

CHUCK:  That’s where I’m kind of hoping that the next versions of Chrome and Firefox and Opera and some of the mobile browsers really will kind of come in and say, “Okay. Our implementation of JavaScript to hit this is the same.” And we can just deal with them with a very clean and common API.

If you’re using Socket.IO or something like that, when you upgrade it, it will just do the right thing. I think the clarification there would be really, really nice.

JAMISON:  Well, now I know what I’m going to do today.

CHUCK:  Yep. So, one other thing that I want to get into a little bit here is I’ve seen some apps in the, not just even necessarily single page applications, but they run into issues when you try and create too many DOM elements, or they run into issues when you try and instantiate too many objects and don’t clean them up. Eventually, they start to fill up memory and then your browser starts complaining. That or it will just hang, in some cases. It seems like if you’re dealing with, for example again, we’ll go to the dental app because I like the example. But, let’s say…

JAMISON:  Do you want to become a dentist, Chuck?

CHUCK:  My dad’s a dentist.

JAMISON:  Okay. [chuckles]

CHUCK:  And we’ve talked about it because he has issues with Dentrix and I don’t think I’m ever going to actually build it. But it’s fun to talk about and it gives me an example that has a lot of different aspects to it.

So, let’s say that he has 10,000 patients or even a million patients.

JAMISON:  Busy man.

CHUCK:  And so, you load the majority of those into memory and your browser and then the thing starts to slow down. Do you run into that with the single page app more frequently than you do other apps? If so, how do you deal with it?

JAMISON:  I don’t know about running into it more frequently than with other apps. But you can definitely deal with it in a few different ways. One classic issue or one classic solution is just to remove stuff that isn’t on the screen. So, if you’re scrolling through something, you have to do your own scrolling to do this. But if you’re scrolling through some gigantic lists then remove the things that are above you that you’ve already scrolled past. Like above some certain threshold so you can still scroll back the other way.

CHUCK:  I’ve seen that. So effectively, what you do is, say it shows ten on the screen, you get 30 more in either direction. And that way if they scroll slowly, they can find them. And if they scroll quickly, then it just gives them ‘you’ve scrolled through 50 million of these’ kind of thing. And then, you get to wherever you are and it loads those in.

JAMISON:  Yeah. About the memory thing, you’re having all the models loaded. If you want all the data, if your data is too big to fit in memory, you’d have to do some similar thing where you’re listening on some kind of an event to know when you need to update the set of data that you have in memory use.

AJ:  Yeah. I think that question generally points more to user experience because yeah, I’ve loaded 10,000 elements on a page before and it takes a heck a long time. And then when you scroll, it’s like your CPU fan turns on, right?

[laughter]

JAMISON:  [crosstalk] …ESPN.com

[laughter]

AJ:  But that’s more of a thing where that’s a prototype situation, in what real life situation. And I bring this up all the time and I always have somebody that’s going to argue the other side with me but I have never understood it, still. In what situation are you going to be displaying 10,000 items to a user? In what situation is that even desirable? When are you designing this experience and you say, “Oh! You know, we’d make this better if there were 10,000 items on the screen!”

JAMISON:  What if your client is Scrooge McDuck and he wants to see all of his dollar bills individually laid out? Boom! Millions and millions of elements.

[laughter]

AJ:  No, what you do is you just hack Solitaire on Windows and you play it till the point where it’s going to win and you have it do dollars instead of face cards.

[laughter]

CHUCK:  But effectively, if you had to do something like that again, you can place some of those scrolling tricks. So, you show what will show on the screen, you show what will show on the next two screens down if they scroll, and then you play that game. So, they scroll and it creates a scroll event that shows the right thing as they scroll by without actually loading all of those elements into memory.

JAMISON:  So, let me make sure I understand you, AJ. You’re saying that if you are ever in a situation where you need to individually look through tens of thousands of items, then you would advocate stepping back and saying there’s got to be some way to summarize these and then be able to drill down to the exact ones that you want instead of just showing everything, right?

AJ:  Yeah. And for that, I’m going to site some research that I can’t remember how to get to it.

[laughter]

AJ:  But there’s the thing where…

JAMISON:  Man, if you were on Wikipedia, I would write the snarkiest comment about this.

AJ:  [laughs] There’s this thing where there’s number of dots on the screen. So like, there’s a bunch of blue circles, right? And then, you’re supposed to be able to say how many blue circles there are. Then the next experiment is you make some of the blue circles like ten times larger. And so you say, “Find all the blue circles that are the big ones.” Then on the next screen, you have blue circles but then you have blue squares and you say, “Find all the ones that are squares.” Then on the next screen, you have the blue circles but then you have the red circles and you say, “Find all the ones that are red.”

The purpose of the experiment was to find out how do people most easily recognize distinct data sets? And the way that you do it is that they find that it’s through color. If you color the ones red, then people can tell you approximately how many are on the screen way faster than if you make them a different shape or if you make them a different size, kind of thing. So, that’s the basic data problem. Of these 10,000 pieces of information, how are you going to make them distinct so you’d even know which ones are important to you at the time anyway?

CHUCK:  Alright. So, I want to get to another question that I have about single page apps and that’s really — it seems like it’s real easy to build multiple page apps. In some cases, I think it probably makes sense to do it and in some cases, it probably doesn’t. In your opinions, when do you want to definitely go with the single page app and when would you definitely not want to?

JAMISON:  Part of it comes down to how well — is your data a series of documents? And does it respond well to being represented like that?

AJ:  What do you mean? A series of documents. 

JAMISON:  So, say you’re building, I don’t know, some viewer for academic papers or something. Those are documents. And you can probably think of some different ways to organize them. But in the end, you’re going to want to go through a bunch of documents, like some review of all the papers by some author, that’s the document. And then the individual papers are documents. Actually now that I’m saying this, you could…

AJ:  The documents are the 10,000 items?

JAMISON:  [laughs] Only if you’re Donald Knuth with a jillion papers. Then again, I guess you could still do a document based app as a single page app. You just use hash changes and stuff, going to the server and getting the page. I’ve convinced myself that I don’t want to.

CHUCK:  What about you, AJ?

AJ:  I think ideally, every app should be able to be a single page app. In my ideal world, an application would be something that I call in a NIT function and pass in the route element and the application would just instantiate itself on top of the route element. And so, I could have multiple applications on a page, or multiple widgets, or whatever.

To be a little more realistic, I would say, “Do one thing and do it well.” So, if you’re getting outside of the scope of your purpose for the 90% of what the user wants to do, then create a different app. Like it makes sense that the write app, the presentation app, and the draw app are all different in Google drive.

CHUCK:  Yeah. I tend to agree. In fact, I was going to basically say that in most cases, it seems like most apps could go either way. And it really just comes down to where you want to manage the switching. Whether you want it to be managed through the standard HTML or HTTP, or whether you’re more comfortable managing it in JavaScript.

But I like the idea of splitting it up if you have multiple apps that have multiple responsibilities. So for example, if you were doing the dental app, you would have your Patient Management and your Scheduling as two different apps and they would be two different pages. And that way, you can keep your domains from cluttering the same space and you can think of them separately. But even then, you could just make those different states in your single page app and then clear one off and put the other one on. So, I think really, what it comes down to is where are you most comfortable managing these different layers?

JAMISON:  So there are some apps that you definitely need to make them single page apps. If you’re trying to recreate a desktop-like experience, like if you’re actually making an app not a series of pages then for sure, you want to do a single page app.

But yeah, I think you’re right, Chuck. There are lots that could go either way and it depends on if you like JavaScript and you want to do lots of client side stuff and have a simpler server, a simpler backend, then it makes a lot of sense if you’re not comfortable. Like there’s some people that don’t like the workflow. You want to make a change so you have to change some stuff in your API. And then, you have to change some stuff in your templates, and then in your CSS files that go with that template and then with your JavaScript files that go with that.  Some people, that really drives them crazy.

AJ:  Isn’t that the same either way?

JAMISON:  What do you mean?

AJ:  Like in single page/multi-page, how is that process different? That sounds like the same thing to me. You still have to change your JavaScript. You still have to change your CSS.

JAMISON:  No, not if you’re just sending down rendered HTML.

AJ:  Well, you’ve got to change what renders the HTML.

JAMISON:  Yeah, right.

CHUCK:  Yeah. So for example, it’s really easy to put an anchor tag in that says, “Go to this other page.” Really easy to do that, you just put it in. The flip side is that in JavaScript, it’s also really simple to create an event that will go and change the state of your page. The initialization for the new page that’s loaded if you follow a link versus the work that’s done when you change state, there really isn’t a whole lot of difference there because they’re going to have to do the same work to provide the same functionality. So really, all we’re talking about is how you manage that transition.

AJ:  One counter argument that I can provide, though, from my own experience is when you’re working with a designer who is not a developer and you’re trying to do the single page app, you definitely cannot be using straight HTML. And I’d hope that no one listening to this podcast has ever concluded that straight HTML is the way to go. You definitely have to be using something like Jade where you can have your widgets completely separate so the designer can render just that one widget as a Jade to HTML and view it. Because if they don’t have the JavaScript on the server end and they’re trying to figure out what the thing looks like, then it is much more difficult for them to work with you on a single page app. Unless you’ve considered that and you’ve designed it such that things are separated so that they can see what a view looks like without having to have the full application running.

JAMISON:  That’s a great point. When we’ve done that in the past, we just have to throw up some dummy view that they could navigate to and have fake data. But it seems like that’s something you could consider. Like you said, you could build that into your application so that every view could potentially just be rendered on its own page in development mode or something.

Do you guys know of anything out there that does that?

CHUCK:  No, not off the top of my head.

AJ:  I just create my templates using dummy data and I separate them out so that when the app is built, it all gets included. All the CSS gets included in one file using Less, all of the HTML gets included in one file using Jade, all the JavaScript in one file using Pack Manager.

JAMISON:  Good, that’s how we do it too. But it would be cool if you could turn on some flag in your app. And then, maybe if you navigate to the path of your template, then it would just render it.

[crosstalk]

AJ:  There you go with the PushState/PopState, right? So with PushState/PopState, you can have your link be the path to the rendered template so that if they’re viewing it statically, then it would take them to the rendered template. But then when your application’s running, if you’re using PushState/PopState, then when they click on the link, it would just execute that Git Rest routing mechanism.

CHUCK:  Yeah, that makes sense. One other thing that comes to mind and this is something that I do in some cases is that I’ll just have some default data like you guys said, dummy data. And then, if you go to it and you pass at the right flags, then it will load it up in development mode and just show it to you with the default data in it. I don’t know if there’s a good package that will do that. But it seems like something that would be relatively simple to build.

We’re running out of time. So, I’m just going to go ahead and cut right over to the picks. Jamison, why don’t you start us off?

JAMISON:  Oh, I have notes but I forgot to get the actual names of my thing. Can you kind of pull in AJ and to pass it on to AJ while I Google stuff really quick.

AJ:  Sweet. So, did I already mention Simple? The banking?

JAMISON:  I think you did, maybe?

CHUCK:  Mention it again. Go ahead.

AJ:  Okay. Well, I’ll mention it again. Simple is a company that technically is not a bank but they run on top of a brandable bank. So, it’s like when you have kind of a big company and like they have their own bank. But really, they don’t have their own bank, they have a bank behind them that allows them to have a webpage with all the branding and all the paperwork has all the branding et cetera, et cetera.

Simple is a user interaction company that rebrands a bank. So, every interaction that you have with Simple, is a very simple interaction and is very pleasurable. Their app on the iPhone works really well. Their website is mostly intuitive, definitely better than any banking website I’ve ever used in my life. And they’re not focused on giving you the best saving rates and they’re not a mutual fund company. Their thing is just they do away with all the bank fees and all the complicated stuff you don’t like about dealing with your bank, and basically, just a checking account for your day to day stuff, not for your investments.

JAMISON:  Simple is great. I second it.

AJ:  Oh, you’re using it now too?

JAMISON:  I have some money in it. My wife is still a little skeptical about it but it’s sweet.

AJ:  I still have my invite. One friend that was going to do it, I think they’re Android app isn’t ready yet or maybe it wasn’t at the time that I extended the invite. So, he didn’t end up joining. So, I still have my invite.

CHUCK:  Alright. Jamison, what are your picks?

JAMISON:  I’m ready. Okay. One is a website which also has a newsletter called CodingForInterviews.com. The name is a little misleading. It sends you those classic interview questions, like “How would you code up a binder search tree?” Or stuff like that. Just kind of like basic data structures and algorithms’ questions and little challenges. I think these are terrible interview questions but it’s really fun to just have a little practice task thing to do. And they shouldn’t take super long to do or, at least, to just think about. So, I don’t use them actually for interviews or preparing for interviews but they’re just fun little exercises. So you can just go to that website.

AJ:  What’s the site?

CHUCK:  CodingForInterviews.com.

JAMISON:  So anyway, my next pick is a blog post called ‘What Does Randomness Look Like’. I’ll paste it in here. It’s on a great scientific blog that I also found lots of good stuff on. But this one’s all about, how do you determine whether some pattern is random or whether some events actually are random or not? And it gets into a little bit of statistics but it’s a really gentle introduction and very easy to understand and really well-written too. So, I really liked it. Those are my picks.

AJ:  You are so well-read, Jamison. I love…

JAMISON:  If I was well done, then that would be good, being well-read isn’t that great of an accomplishment.

AJ:  Well, whatever dude!

JAMISON:  But thank you, AJ.

AJ:  I wish that I still worked in the same office as you, because I always loved your little random tidbits of, “I read this article and I learned this cool thing.” It was always enlightening.

JAMISON:  Thank you.

AJ:  Now, we’ve got some dead space because Chuck is apparently taking care of business.

JAMISON:  It’s his time to accidentally mute his microphone?

AJ:  So I did want to plug myself a little bit because I am now an independent consultant. And so if you want me, your test of skill is to figure out how to get my Email address from Googling for it.

[laughter]

AJ:  Because if you can’t, it’s probably not going to work out.

JAMISON:  What kind of stuff are you looking to do? Client side? Server side?

AJ:  Yeah, just JavaScript [crosstalk].

JAMISON:  Massages?

AJ:  Yeah, I’ve definitely given out massages. That’s definitely part of the kind of work I’m looking for.

[laughter]

CHUCK:  Alright. Sorry.

JAMISON:  Oh, Chuck. We were lost without you.

CHUCK:  Yeah, I’m sure you were.

AJ:  That’s okay. I just started shamelessly plugging myself.

CHUCK:  That’s fine. We’ll get it all edited out.

AJ:  No!

[laughter]

CHUCK:  Alright. I guess it’s my turn for picks. My first pick is my chair. I just bought a new office chair. I don’t know if you guys saw the pictures. Maybe I’ll put links to the tweets that had the pictures on.

JAMISON:  Yeah, I saw those.

CHUCK:  Yeah. I wound up flat on my back on the floor because my chair broke.

JAMISON:  Were you leaning back on your chair? My mom always told me not to do that or it would break.

CHUCK:  It was made to lean back. It just wasn’t made to lean back like that apparently.

So anyway, I bought a new chair and this is the second chair I’ve broken, I think. No. I replaced the chair before it because it would squeak when I was sitting in it during my podcasts. So I would shift my weight and it would be like, “Squeeeaaak!”

JAMISON:  I remember hearing your squeaky chair.

CHUCK:  Yeah. So, I got that chair. Well, my wife got it for me for Christmas last year and it broke just before Christmas this year. So, I talked her into letting me buy a Herman Miller Aeron Chair.

JAMISON:  Wow!

CHUCK:  And yeah, they’re not cheap chairs but I’ll tell you…

JAMISON:  That’s how you know you’re loved.

CHUCK:  I’ve been sitting in this chair all morning and it feels terrific. I got the adjustable lumbar support on it. So, it kind of puts my back in the right position. The arm rests are about the right height and it tells you how to adjust it to take the pressure off of the right areas of your body. It’s just been really, really nice. It’s a lot more comfortable than my last chairs. So, I’m definitely going to pick it.

My other pick is a website that I use a lot of times. And this is not a technical pick at all, but this is a website that I use when I get into the mood to cook some food. I go to AllRecipes.com. And they have recipes for all kinds of stuff. Sometimes, I’ll do marinades and then I’ll go grill something. Sometimes, I’ll get recipes for the crock pot. The crock pot’s been my favorite for a while now, just because I can just dump a bunch of stuff in it and then, we have dinner at night because I left it on all day. So, that’s a good way to go. My wife and I have been eating a lot like crap lately. So, we’ve been eating all the goodies and stuff that you get from the holidays.

JAMISON:  Yes, it’s Christmas tradition.

CHUCK:  So we are looking at cutting that out and getting back on track with our healthy living. So, AllRecipes has a lot of great recipes for that. It’s cheaper than eating out and all that anyway, to cook your own food.

JAMISON:  I don’t know about that cheaper than eating out. Fresh fruits and vegetables are expensive.

CHUCK:  Yeah. Well, it depends on where you go to get them too. And it depends on how you’re using them. If that’s all you’re eating, then they are kind of expensive. But in my case, generally, I go buy. I’m really hankering for some chili. So, I’m thinking about going to the store and getting some ground beef and some beans and stuff and just putting that in the crock pot and cooking it up. Of course, I can’t add a whole lot of peppers because my wife and my kids won’t eat it if I do. You know, just stuff like that.

So, you get a good meal together and then you’ll wind up eating it for a few days sometimes because you made a lot of it. But the nice thing about it too is that if you’re cooking for a family, I think you really get the savings out of this kind of thing. Because you just put a couple of little portions out for the kids and then you eat yourself. Anyway, it’s good deal but they have some terrific recipes and they have them pretty well broken out. Great recipes.

So, I’ll pick four or five. I’ve been rambling on these for a while. I’ll pick four or five and then, I’ll print them out. I’ll go buy all the ingredients and then I’ll cook every other day for my family for a week or two.

AJ:  Do they have a shopping cart thing?

CHUCK:  No. I wish they did.

JAMISON:  Don’t they have a thing where you can put in like, “This is the crap I have in my fridge. And I don’t want to eat Ramen again. What can I make with this?”

CHUCK:  I haven’t seen that either.

[crosstalk]

AJ:  I think that would be MyRecipes because like AllRecipes, MyRecipes, and then FoodNetwork are the big three sites.

JAMISON:  Yeah, MySpace and Facebook.

[crosstalk]

JAMISON:  Do you know what Hadoop is? Isn’t that a recipes guide or something like that?

CHUCK:  MyRecipes, it looks like it has a, “What’s in your pantry?”

JAMISON:  Neither of your guys even laughed at my hilarious Hadoop joke. Come on!

AJ:  You must have been shushed or something.

CHUCK:  No. I heard it. I didn’t think it was that funny.

JAMISON:  Ohh. Yeah, I must have been shushed. [laughs]

AJ:  I was trying to save you. [laughs]

CHUCK:  Yeah. I’m looking at these different websites. A shopping list on AllRecipes would be really super nice. In fact, I’ve thought about actually seeing if they have an API and then kind of doing that myself. So, it’s like building an app that basically says, “These are the recipes that you’ve made off of AllRecipes. Do you want to make them again? Yes.” And then yeah, have it build you a shopping list. Anyway, maybe I’m just looking at the wrong coding site.

AJ:  You could totally do it, make a little bookmark widget with jQuery.

CHUCK:  That’s not a bad idea.

JAMISON:  I like doing that kind of stuff when I don’t feel like doing real work. But I just kind of want to nibble on some code for a bit, just find a site to scrape.

[laughs]

CHUCK:  Well, I have been — I’m going to start putting up videos on TeachMeToGo.com again. And so, I might do that for one of them, just be like, “Hey, I’ve been wanting this. So, dang it!” Then if you’re on a recipe page, it’s like, “Add this recipe to my list.” And then, it puts the recipe in your list and then it puts the shopping list together. And so, you can just print the whole thing and it print the recipe, it prints the shopping list and it does all that good stuff. Anyway, so yeah, those are my picks.

The chair I like a whole bunch more than AllRecipes, and AllRecipes got way more time.

Anyway, so we’ll wrap this up. In two weeks, we’re going to be talking to…

JAMISON:  David Herman?

CHUCK:  David Herman about Effective JavaScript. So, read the book and we’ll get him on the show and we’ll talk to him about it.

JAMISON:  It’s super good. It’s a really good book. I say that every week. It’s still true every week. It’s a great read.

CHUCK:  So, I am going to warn you. It is scheduled for us to record that on the 10th but I’m going to be out of town. So, we may move it just because I want to be on the show and I have the power.

Anyway, so other than that, we will wrap this up. I’ll catch you all in a week.

JAMISON:  Alright, see you guys.

CHUCK:  Bye.

AJ:  See ya.

2 comments
Joeri Sebrechts
Joeri Sebrechts

Just my 2 cents having built a 100K line single page js app over the past 5 years... As discussed, i agree that a single page js app makes most sense if you have to build a desktop-like app, not just a sequence of semi-intelligent pages. We came to the single page architecture out of the necessity of gradually porting a several million line delphi- written windows app to the web. You cannot get the "feel" of a desktop app across a page reload (whole or partial). One topic that wasn't discussed was that the server-side gets reduced to just a set of web services. In our case those services don't even return html, just raw data. They get consumed by our javascript front-ends (desktop and mobile, extjs and sencha touch), but also by native mobile apps, third party software bindings, and so on. This dramatically simplifies the server-side code, and the clean client-server boundary helps with security architecture. Another big plus is that the entire front-end is static javascript. You can throw it onto a CDN to get better performance than you could get from a server-side front-end, and again this makes it easier to build a secure app, as your trusted/untrusted boundary lines up perfectly with client/server boundary. I think if more developers tried out their web apps across a 2 second latency proxy, they would do more in-page without server roundtrips. Another thing that this enables is having proper client-side components. In our case each feature screen is a widget, itself composed out of widgets, all the way down to individual form controls. We have a ton of custom widgets. Everything is tied together with events. The widgets all use a theme (extjs theme) so there is no need for a graphic designer to be involved in the actual development process (just like building a desktop app). Basically, we never deal directly with the DOM when implementing features, because the DOM is too low level to build UI at scale. This means that our internal architecture is very similar to a desktop app. Now, there are downsides, and i felt the downsides were treated too casually. First of all, the developers have to break away from the series of pages model and into the hierarchy of widgets model, and they have to be really good at javascript to write it "at scale". Most developers still try to treat it like a series of pages, and this model quickly breaks down. A classic example is routing. You can spend a lot of time getting routing to work, so the back button remains functional. But the advantage to the user is often marginal at best, and that dev effort could produce more value elsewhere. You have to reason about it like a desktop app, and often desktop apps don't have back buttons either, for good reason. This extends to many of the underlying assumptions of how web pages should be built. I've found that the combined hurdle of switching mental model and beefing up javascript knowledge can really drag you down when onboarding people. So, not a great strategy if you plan on growing a team quickly unless you compensate for it with tons of onboarding tutorials. Secondly, managing the lifecycle of different views becomes really important. You have to think about when to load code (loading it all upfront becomes infeasible past a certain point), when to render UI, what parts of the UI not to render yet (e.g. tab content shouldn't get rendered until the tab is activated), and when to clean up UI and associated data (unbind all listeners, remove from DOM, remove data stores, ...). This can't be handled at the feature level without it becoming a huge mess, so you have to use a framework that solves those generically. That was a large part of the reason we chose extjs at the time. So, in conclusion: if what you want to build is essentially a desktop app in a browser, a single-page architecture can work well, but you have to think up-front about a lot of things that you otherwise wouldn't worry about. If your app is still essentially a series of pages, don't go the single-page route, as the headaches won't be worth the result.

Trackbacks

  1. [...] 041 JSJ Single Page Applications (Charles Max Wood, AJ O’Neal, Jamison Dance, Joe Eames, Tim Caswell, Merrick Christensen) [...]

Previous post:

Next post: