AIMEE:
Speaking of awesomeness, you have the coolest name ever.
[This episode is sponsored by Frontend Masters. They have a terrific lineup of live courses you can attend either online or in person. They also have a terrific backlog of courses you can watch including JavaScript the Good Parts, Build Web Applications with Node.js, AngularJS In-Depth, and Advanced JavaScript. You can go check them out at FrontEndMasters.com.]
[This episode is sponsored by Hired.com. Every week on Hired, they run an auction where over a thousand tech companies in San Francisco, New York, and L.A. bid on JavaScript developers, providing them with salary and equity upfront. The average JavaScript developer gets an average of 5 to 15 introductory offers and an average salary offer of $130,000 a year. Users can either accept an offer and go right into interviewing with the company or deny them without any continuing obligations. It’s totally free for users. And when you’re hired, they also give you a $2,000 bonus as a thank you for using them. But if you use the JavaScript Jabber link, you’ll get a $4,000 bonus instead. Finally, if you’re not looking for a job and know someone who is, you can refer them to Hired and get a $1,337 bonus if they accept a job. Go sign up at Hired.com/JavaScriptJabber.]
[This episode is sponsored by Wijmo 5, a brand new generation of JavaScript controls. A pretty amazing line of HTML5 and JavaScript products for enterprise application development in that Wijmo 5 leverages ECMAScript 5 and each control ships with AngularJS directives. Check out the faster, lighter, and more mobile Wijmo 5.]
[This episode is brought to you by Braintree. If you’re a developer or manager of a mobile app and searching for the right payments API, check out Braintree. Braintree’s new v.zero SDK makes it easy to support multiple mobile payment types with one simple integration. To learn more and to try out their sandbox, go to BrainTreePayments.com/JavaScriptJabber.]
CHUCK:
Hey everybody and welcome to episode 164 of the JavaScript Jabber show. This week on our panel we have AJ O'Neal.
AJ:
Yo, yo, yo, coming at you live from sunny desert-like Provo, Utah.
CHUCK:
Aimee Knight.
AIMEE:
Hello.
CHUCK:
I'm Charles Max Wood from DevChat.tv. I just want to make a quick mention. You know we did JS Remote Conf. I am now doing Ruby Remote Conf. So, if you're into Ruby, go check it out, RubyRemoteConf.com. We also have a special guest this week and that is Spike Brehm.
SPIKE:
Hello, hello. My name is Spike and I'm an engineer at Airbnb.
CHUCK:
Do you want to kind of explain a little bit more about what you do?
SPIKE:
Sure. I'm a web engineer. I've been at Airbnb for the last four years or so. And I mostly build things with JavaScript and Ruby. And recently I've been trying to figure out how to share code between the client and the server, something that some people call isomorphic JavaScript. Some people hate that word, but basically trying to figure out how to share an application on both sides of the wire. So, I do that. Then I also play some bass guitar on the weekends. And I think that's about it.
CHUCK:
Very nice. Now, four years at Airbnb. That's like forever in developer career time, right?
SPIKE:
Yeah, it's been a long time.
CHUCK:
So, we brought you on to talk about Rendr. That's R-E-N-D-R.
SPIKE:
That's right, [dropped vowel].
CHUCK:
Do you want to explain the idea behind it? You mentioned isomorphic JavaScript.
SPIKE:
Yeah, absolutely. So, Rendr is an open source JavaScript library that we created at Airbnb. You can check it out on GitHub if you like. It's GitHub.com/rendrjs/rendr. And basically it's one of the first open source isomorphic web frameworks. So basically, what it lets you do is it lets you take a single-page app and render it on the server side. So, it's built on Backbone and Handlebars. You can basically build a Backbone/Handlebars single-page app. But then it also has some components that run on Express and Node.js. And so, the whole idea of it is that you can basically server-render any deep link of your single-page app. Any page for your single-page app will be fully rendered on the server. But once the page loads and the JavaScript initializes and all that, it just turns into a typical single-page app. And it's all client rendering from there on out.
CHUCK:
It's really interesting. So basically, if you've built your app as a single-page app on Backbone.js, you can just pull it down to the server and have it render there instead?
SPIKE:
That's right, yeah. And…
CHUCK:
It's really that simple?
SPIKE:
It's [chuckles]
CHUCK:
I'm sorry if I sound a little incredulous, but yeah.
SPIKE:
No, no, you should be incredulous. It's not quite that simple because you have to build it in a particular way. So, whenever you're building, whenever you're writing JavaScript that is isomorphic or could be run in multiple environments, you have to be really careful because you don't want to just say window.whatever, document.body, you have to be careful which global objects you access in certain spots because you could accidentally blow something up if you're running that on the client and the server. So, Rendr basically provides a little bit of structure to your app. And the application folder, the directory structure is based… it's like a hybrid of a Rails app and a Backbone app, which makes sense because it's like server and client.
But it provides a few basic building blocks that you can build your app on. And the first are routes. So, routes just map URL patterns to controllers and actions. And then Rendr also provides a controller. And controllers basically just specify how to fetch data for the given page. And these controllers in the routes are run both on the client and the server. And so, all they do is for example, the example app that ships with the repo is basically a little GitHub app that uses the public GitHub API to just list, show off different projects and whatnot. So in the project, or the repo, show controller action, the only responsibility of that controller is to specify what the data is, so basically which models or which collections to fetch.
And so, Rendr also provides a model base class and a view base class. And these are both subclasses of Backbone model, Backbone view. And they just make it more simple to handle the fact that your app will be rendered both on the server and the client. And will handle fetching data in a way that uses the same patterns and semantics on both sides of the wire.
AIMEE:
So, maybe a more basic question to back up a little bit. I'm somewhat new to programming. And so, when I started programming I started in Rails which you're rendering things on the server. But then I started seeing all of these JavaScript frameworks coming out. So, you're starting to do more on the client. And now, it's like we're going back to the server but for the page loads though. Maybe explain why the back and forth?
SPIKE:
That's a really good summary of the way the web has progressed over the last decade or so. Everything used to be purely rendered server-side. That's the way that web browsers initially worked. And then as web browsers got more powerful and CPUs got more powerful, the JavaScript runtimes kept getting faster. And we saw the second generation of browser wars between Chrome and Firefox. And IE has been actually catching up, but their JavaScript runtimes have been getting faster and faster and faster. And there have been all these new features, these new features of the web platform. So, all the HTML5 stuff, local storage and push state and all these [tens and tens] of different features that all put together provide more of a Rail-like application platform for the web, whereas the web used to be just a collection of pages.
So, as we've seen the browsers evolve, we've been able to do more and more with JavaScript. And people have started to build these full apps just in JavaScript. At Airbnb we went down that route for sure when we discovered Backbone, Handlebars and a lot of these tools. We started building this really thick client, single-page apps. And we did it for a few reasons. One of the reasons is because we just could. [Chuckles] As frontend engineers, as JavaScript people we're like, “Oh my god, this is so cool. We can build this whole app just in JavaScript.” And it is a nice development model because as you're building things with more interaction, more rich interactions, more complicated interactions, it doesn't make a lot of sense to split your code, split that feature between for example Ruby on the server side and JavaScript on the client.
You've probably written a lot of code before, but you embed some maybe data attributes in the HTML on the Ruby side and then in JavaScript you pull them out. And there's just… it's kind of a broken development model really, for building rich user interfaces when it's split between these different languages, one on the server, one on the client. And so, that's part of what made full JavaScript applications really popular, because you can have all of your views, all of your templates and all that, all on the client side. And then it's a really nice way of building an app because you can have a REST API, some sort of JSON API that you deal with. And that's a really nice, clean separation of concerns. So single-page apps became all the rage.
And we saw a lot of libraries pop up and frameworks pop up like Backbone and Angular and Ember and SproutCore. And there's so many. It's kind of a joke that every JavaScript engineer, every frontend engineer, once they reach a certain level of maturity or experience, maybe sophomore level engineers, they'll write their own MVC framework because they can. And so, we saw an explosion of that.
But the reason that things are moving back to the server side is a few related reasons. But basically we're realizing that it's very valuable to be able to render markup, render HTML on the server side. Because the alternative, like just the typical single-page app approach is to basically serve a blank HTML page from the server with an empty placeholder div. And then when the JavaScript app initializes on the client-side, it'll generate HTML and stick that HTML in that div. And there's your app. But that means you're basically serving blank HTML pages.
And so, the first reason that we started looking into moving back to the server is SEO reasons. Because we were doing all these weird hacks where in Ruby we would kind of copy our templates and try to get the same semantic markup and content on the server as was rendered on the client and try to keep them up to date and everything for the search engines to crawl us.
AJ:
So, I hear this argument. I'm definitely very much on the other side. I believe in rendering on the client where it belongs. But… [Laughter]
AJ:
I also…
CHUCK:
That wasn't a biased statement at all.
AJ:
Well, no. There are some huge advantages that maybe I can go into later. But so you say you need to render this content for SEO. Why do you need to render content for SEO? Because it seems like if a user's logged in, they're going to get stuff that's personal to them. So, there doesn't a need to be any SEO. I don't want Google searching my Gmail account because I don't want Google logging into my Gmail account, right?
CHUCK:
Yeah, but what about something like Airbnb where you've got a room in a city, maybe in a specific neighborhood where somebody's going to want to stay, they want that indexed.
AJ:
Right. So, why not generate that and just serve it statically? What's the component that must be done dynamically?
SPIKE:
I think it is a good point that if your app is completely behind a login, then the SEO is not a concern for you.
AJ:
Well, not that it's completely behind a login. But generally the stuff that's dynamic is stuff that's specific to a user, or that's specific to a search, which a search engine isn't going to be typing in searches on your site. They might… anyway, so I'll let you go on.
SPIKE:
Sure. Yeah, that's a great question. So, if you were to look at our listing page or our search page, we do render them server-side for the SEO reasons. But we want them to be interactive experiences. And the search page is maybe more a better example. It's more interactive. As you browse, you change your different search filters, you pan around the map, you interact with the different things, you paginate through results, it's all dynamically updating the URL using push state and doing all sorts of other rich UI things. And so, at that point you're living in both worlds where you're starting out rendering a fairly static page on the server. But then you also want that to be a rich dynamic experience for the user. And I think that's a weird limbo to be in. Does that make sense?
AJ:
Yeah, I'm not entirely sure. Because if I'm interacting with something, if I'm putting in data that's something that a search engine isn't going to be doing. So, it makes sense for that to just be done on the client. But I guess I could see cases where it's not intuitively obvious how to have the dynamic part on a page that you're serving statically.
SPIKE:
Sure, yeah. And a lot of times even on our listing page, most of the page is pretty static. But once you start to input dates and interact with the buttons and whatnot that becomes a fairly rich, dynamic experience. And so, you have to choose if we want to go full client-side of that feature, which is a better development experience because you can have your templates and all that stuff rendered in the client. I would much rather be able to render client-side for those rich features. But then do you duplicate that on the server? Or do you just do a halfway approach where it's serverrendered and then you just do a bunch of silly DOM manipulation with jQuery? So, I think that's where it starts to get painful, when you're bridging that divide between a static page that then becomes dynamic as users interact with it and all.
AIMEE:
I really like the waterfall graph that you used in your presentation. So, we definitely should link to that. And I don't know if now would be an okay time to try to explain it a little bit.
SPIKE:
Oh, sure, yeah. Right, so SEO was the first thing that I mentioned. With the [13:57] we were interested in this approach. But what really became apparent to us as the reason why we should be doing this is performance.
And Twitter has a really good blog post about this. I think it's around 2012 when Twitter used to be… they used to have the hash-bangs in the URL back in the day. So, Twitter.com/#!<someone's user name> or something. And that was really cool. For all of us that were watching at that time we're like, “Man, they're doing client-side rendering. And it's fetching from the API. That's so cool.” And it was cool. Like once you got that page loaded, you could really speed around and click on links. And it's a very dynamic experience. But what they did, Twitter spent a year and 40 engineers basically rewriting all of that to render server-side instead.
And the reason they did that is for performance. And they had this metric that was called 'time to first tweet' which basically is how long does it take for example clicking on a link to a Twitter page from Google and actually being able to see that first tweet rendered on the page. And it turned out that time to first tweet was really, really poor for client-side rendered apps because basically the first thing that happens when the browser starts to download that page is it downloads a skeleton HTML page, so the page without the real content in there, just a placeholder for the content to be inserted. And then the browser will find a script tag and it downloads the JavaScript. And then it evaluates the JavaScript and parses it.
And then and only then because they're using the hash-bang, and if you may recall the hash-bang, it's not part of the HTTP spec at all. It's just a hack. So, that hash never even gets sent to the server. So, once all that JavaScript is downloaded and evaluated, then it looks at the URL and figures out which API endpoint to call. And then it calls that. You know, you wait a few hundred milliseconds for that to return. And then finally that returns and you can render your HTML and the user will see the content. And that's a lot of steps to happen. Whereas if you just render on the server side, as soon as that HTML has been streamed to the browser, the user can see it and interact with it.
AJ:
So, that… I do want to point out that the case you’re talking about there is the case where the person has never visited the site before, right?
SPIKE:
Oh, not necessarily.
AJ:
And so, they’re visiting it for the first time and the browser has to download all of that because none if it’s in cache. Or, they’re not using any of the cache mechanisms that are available.
CHUCK:
That can be true. I don’t know if it is always true.
SPIKE:
We found that you can’t really rely on caching for a number of reasons. Like sometimes there are weird proxies that get involved for the user and screws up caching. And also, for us we deploy 10 or 20 times a day. So, the chance that you’re hitting a cached bundle is not that high, the cache hit isn’t that high.
AJ:
Okay.
SPIKE:
But yeah. That’s true. But when you’re trying to really… like [16:50] the success of your app, of your website, you really want to capture a user’s first interaction with your app. That’s the most important one, right? People, they don’t have any loyalty yet to you. So, that’s when you need to grab them.
And just to finish the Twitter anecdote, they found that they reduced the time to first tweet by five times, so 500% by going back to server rendering. So, that’s pretty significant.
CHUCK:
So, does that affect the way that you can scale? Because it seems like that’s the tradeoff, is that if I don’t have to do as much processing on the server then I don’t need as many servers to serve stuff up.
SPIKE:
Yeah, for sure. It could. It could. Although I don’t think that typically, like web servers and basically rendering HTML in Ruby for example, I don’t think that tends to be the biggest bottleneck.
CHUCK:
Right.
SPIKE:
It’s usually the database load or more of the API tier. But for sure, there would be lots of computation happening on the server for client-side rendering.
CHUCK:
Right, fair enough.
AJ:
And I guess if you are targeting really terrible devices, like Android 2.3, I could totally see where a server-side render is going to be faster.
SPIKE:
Yeah, and that’s a great point because on mobile this issue is super exacerbated because one, like you mentioned is low-power devices. Because they just don’t have a lot of CPU power to parse and evaluate that JavaScript, which can take several hundred milliseconds just to evaluate a couple of hundred kilobyte file, then also these really high latencies on mobile and really low bandwidth. And so, if you look at the best practices for mobile web performance from Google from Ilya Grigorik and Steve Souders and those guys, it’s all about reducing the number of HTTP requests before the user can see your content. So, if you have several JavaScript files and then an API request or two that really adds up to a painful amount on a mobile device. And you just sit there seeing a spinner.
AJ:
Yeah, I’m definitely seeing really poor implementations of client-side code. I’ve seen people do it really, really badly and it really creates a negative user experience. But I’ve also seen it done really well that creates a really great user experience.
SPIKE:
Yeah.
CHUCK:
So, the moral of the story is try it out on your app and see?
SPIKE:
Yeah, I think so. Although I would try it out on maybe an experimental app because if you’re going to go all in with the isomorphic approach, it does enforce a lot of constraints on the way that you build for better or worse.
AJ:
I would have to say those constraints are generally good, though. I don’t know if you can pull up a point that you think has been really bad. But to me, it seems like it leads to better abstraction, like you were talking about where if something isn’t cross-platform or cross-browser or cross-Node and browser, you have to tease it out and focus on logic that then becomes more testable, more universal.
SPIKE:
Yeah, absolutely. I do think in the long run it’s a good constraint for those reasons that you mentioned. But it’s a paradigm shift for people who aren’t used to it. So, you have to break some bad habits sometimes [chuckles] you know?
AJ:
Yeah. Like you have to write in vanilla JS, which everybody uses that word but nobody knows what it means, you know?
SPIKE:
I don’t really know what you mean exactly by that, because it can mean a lot of different things.
AJ:
Well, like you have to write more in actual JavaScript instead of assuming the browser or assuming Node. You have to actually become better at the language of JavaScript rather than the vendor implementations of JavaScript.
SPIKE:
For sure. There’s kind of a lower common denominator and you have to get to do [inaudible]. There are some shims and things you can use. So, one tool that makes this all really possible and really easy are the build tools like Browserify and Webpack. But we’ve got a lot of experience with Browserify. And there’s a really cool feature of Browserify that not many people are aware of. And there’s actually, it’ll support a proprietary field that you can add in your package.json.
So, let’s say that you were going to create some sort of reusable module. I like to use as an example, if you’re trying to create a cookie module, so some sort of module that its only responsibility is to set a cookie. And you want that to work both on the client and the server where the actual implementation for setting a cookie on the client or the server are wildly different, right? On the server you’re setting an HTTP header. On the client you’re just modifying document.cookie. But in both cases the way that you serialize a string is the same. So, it’s a good example of something to abstract out.
And with Browserify, if you were to create a module called set_cookie or you can look at the one that I’ve created on npm called set-cookie, what you can do is you can actually swap out implementations between client and server. So, there’s a field in your package.json called browser. And the browser field can be a simple string. And if it’s a simple string you can basically say for the browser implementation of this module, use this other file. Or it could be more. It could be an object and you could swap out specific files. So then, basically what you can do is you can export a single public API for your module. And then under the hood provide different implementations for Node.js versus for the browser.
And that’s really, really powerful because that means that each module that you use to compose your app can have its own forking logic, its own branching logic determining what’s browser versus client. And so, if you compose these modules together it becomes fairly straightforward to build an app that can run on both sides with just a little bit of glue between.
CHUCK:
So, I’m still having trouble with the exact case where you’d want something like this. Because it seems like if you have a Backbone frontend or some other single-page app and you move that rendering to the backend with your single-page app, don’t you still need the backend for your original application to be running? What exactly are you eliminating by doing this other than the frontend rendering?
SPIKE:
Yeah, so you’re not really eliminating anything. You’re really just adding another step [chuckles]. So, I like to think of… I wish I could show some diagrams on a podcast [chuckles] but I like to think of the Node rendering as just another rendering target.
CHUCK:
Mmhmm.
SPIKE:
So, you can render for the browser and you can render for the server. But in either case there’s a fairly clean separation between your API which is providing JSON basically and then whatever HTML gets generated. And so, in the client, in this typical single-page app you have that really clean separation. And you can maintain that with the server rendering. So for us, for our Rendr apps we have a Rails API that’s providing all of the JSON. And it’s the same Rails API that we use for just pure client-side apps. But now the server and the client can talk to that API.
CHUCK:
Gotcha.
AJ:
That makes sense.
CHUCK:
So, who gets the statically rendered and who gets the dynamically rendered page?
SPIKE:
Yes. [Laughs] Just kidding. Both. So basically, as an example you could check out m.airbnb.com. That’s our mobile webpage, our mobile web app. And basically, if you were to view source on that, any page that you can hit, any search query, any listing page, if you hit that directly for the server it’ll return that full HTML.
CHUCK:
Okay.
SPIKE:
But then once it gets bootstrapped in the client side, once that page loads, it’ll intercept the clicks. And then subsequent clicks, it’ll just be a single-page app. So, I think that maybe the easiest to think about it is it’s just a single-page app that also has the ability to server-render that first page load.
CHUCK:
Okay.
SPIKE:
Does that help?
CHUCK:
Yeah, I think so.
AJ:
So, here’s a question that I have. So, it seems like what you’re saying is when I visit one of these pages, if you give me a link to the page it’s going to render everything about that link on the page. And then I’m going to be able to click on it. And then from that point, it’s now a dynamic page, right?
SPIKE:
Yeah, exactly.
AJ:
So, we’re not in the cycle of hitting the server every single time. We’re just using the server for that initial page load to reap the benefit. And then… now, if I were to try to do this in Angular, you mentioned earlier that you don’t really like Angular.
AIMEE:
[Chuckles]
AJ:
But if I were to try to do this in Angular, one thing that I’d be concerned with is it would be difficult to reconstruct the state of the page.
SPIKE:
Mmhmm.
AJ:
And maybe I just haven’t tried it and so it seems like it would be difficult. But intuitively it seems like it’d be difficult to reconstruct the state of the page so that when I click on something my click handler is already attached and that sort of deal. So, how did you overcome that problem? Or was it not a problem?
SPIKE:
You’ve got a good intuition there. That’s one of the big problems that Rendr solves. That was the hairiest problem probably, because just as you say… so normally, when you do client-side rendering you start with a view. And then you get HTML from it. You start with maybe a hierarchy of views, some sort of nested hierarchy. And then each produces some HTML.
But when the server renders, that happens on the server. It sends a bunch of HTML to the browser and then once your JavaScript app initializes, that DOM is already there. And rather than throwing it all out and replacing it, what you want to do is you want to reattach to it. So, take what’s there and basically reconstruct your view hierarchy on top of it. It would be simple to just throw it out and regenerate it. But then bad things can happen, because what if someone started typing in a form field or stuff like that? Because there is state in the DOM.
So, what we have to do is basically inspect the DOM, look at the DOM, find out which view is associated with it, find out which model class, model id, which collection is associated with each. And then the process that I call it is hydration. So, it basically rehydrates that markup and attaches all of the views to it and the click handlers and makes sure that this .model points to the right object and all that kind of stuff. So, that took some work. But this is a good time to plug React, because React makes this a lot easier. And React does this out of the box.
And so, React wasn’t around when I started working on Rendr. But if it was, that’s what I would have used. And you can actually use React now with Rendr. But there are a lot of things that are special about React. And one of them is that Virtual DOM and its diffing. And so, what happens is if you generate a bunch of React, markup using React on the server and then you hand it to the client, and then you tell React, you point React to that DOM and you basically tell it to render, because of its DOM diffing algorithm that it uses for the Virtual DOM it’ll render that whole React component tree in memory in the Virtual DOM. Then it’ll diff it with what’s actually there and it’ll mutate it if it needs to and it won’t if it doesn’t. And long story short, React basically fixes this problem by design.
AJ:
Okay. So, is React then relying on the event delegation? So, it’s just listening on document.body? It’s not listening on individual elements for its clicks? I don’t really know much about React. So, forgive me if that’s just ignorant and I don’t understand how it works though.
SPIKE:
I don’t know the answer. I imagine it does some delegation.
AJ:
Delegation is definitely way bueno.
SPIKE:
[Chuckles]
AJ:
I don’t think there’s any downside to it. But I just, I know that a lot of frameworks still today will directly attach things in some cases rather than use delegation. I don’t know. I guess the big ones probably all delegate.
SPIKE:
I would think it does that.
CHUCK:
Well, and it seems like a lot of the other frameworks like Angular 2, the upcoming version of Ember, they’re adopting a lot of the approaches that came out in React.
SPIKE:
Absolutely, which I find to be exciting.
CHUCK:
Yeah, totally, because the whole web’s going to come up in quality because of that.
AJ:
So, I was once watching a presentation on Amber JS which is a Smalltalk implementation in JavaScript. And this guy was a Smalltalk guy. And he was talking about this awesome experience where he could actually have a client that was using the client side of an app, like a desktop app, and there could be an error on their server and he would be able to go in, fix the code, and then tell the client to button again. And even though there was an error state, the code was, it was all super functional. So, none of the state was in the code. It was all separate. I didn’t entirely understand. But the point was that an error on the server could be resolved while it was still running. And I think that the idea of having JavaScript where it’s so functional that the state of the DOM isn’t dependent on the code, maybe one day we could get to that point where we can be live-updated UI debugging clients or something. Maybe that’s just a little far out there. [Chuckles]
SPIKE:
Whoa, dude. [Chuckles]
AJ:
Well, there was like a TED talk or something where a guy actually had a prototype implementation of this, too. So, that’s where my mind is going.
SPIKE:
That’s interesting. I think related to that is what’s so cool about the Virtual DOM whether it’s React of the other implementations of that is that the DOM is basically one way. It treats it as something that’s downstream from the state. So, you never have to go look at the DOM to find the state, which is something that I always found myself doing in Backbone apps, is you look, “Oh, does this have this class? What is this data attribute?” You’re doing that two-way synchronization which is a painful thing.
CHUCK:
So, one thing that I am wondering about a little bit is if you are in Rendr basically building or serving, rendering fully-formed HTML are you using components out of Express? Because Backbone and some of these other libraries, they rely heavily on the DOM. And so, since there is no DOM in Node.js are you just creating your own funky little sort of DOM and then rendering that and then sending that back up the line? Or how does that work?
SPIKE:
That’s a good question. So, I wanted to avoid a DOM on the server. There are people who use a DOM on the server, so jsdom or PhantomJS. You can server-render an Angular app by having a headless browser, for example.
CHUCK:
Mmhmm, yeah.
SPIKE:
But DOM is… the conventional wisdom is the DOM is slow. And it’s an unnecessary dependency. So basically, I just do string-based templating on the server with Handlebars, was my first approach.
CHUCK:
Okay.
SPIKE:
Because Handlebars, it just generates a string of HTML and that can be used on the client or the server. And then we do use Express for all of the HTTP stuff. And Rendr, it ships as an Express app that you can mount onto another Express app. It’s a neat feature of Express is you can mount these apps onto each other. But so, it’s basically just a string-based templating and avoids the DOM on the server entirely.
CHUCK:
Okay.
AJ:
So, will you explain what you mean exactly. You mount it on top of another app. Do you mean like such that it accesses the JSON API kind of thing?
SPIKE:
In this case, so you know how Express has middleware?
AJ:
Yeah.
SPIKE:
And you can basically mount a middleware at a certain URL path.
AJ:
Yeah, yeah. So, when I think of mounting I think app.use/api and then I give it a router and then router accepts some rest.get, rest.post, rest.put.
SPIKE:
Totally. Yeah, so a cool feature of Express is that if you create an Express app you can treat that entire app as a middleware. You can say app.use/app or something. And then for the second argument you can just give it an Express app instance.
AJ:
Right.
SPIKE:
Instead of a middleware function. And then it’ll just stick that whole, it’ll treat that whole app as a middleware in your higher level app. [Chuckles] [Inaudible]
AJ:
So, it’s essentially the same thing as virtual hosting except that it’s by path instead of by subdomain?
SPIKE:
Yeah, totally. And then you can even mount it at the root as well. And it’s just a nice way of encapsulating error handling logic and all that kind of stuff.
AJ:
Okay.
SPIKE:
So, we’ve talked so far about rendering single-age apps. I think that’s one interesting use case for isomorphic JavaScript. And that’s what I’ve done with Rendr. But there are a few other really novel use cases of this which take advantage of the fact that you can share code between client and server. And so, that second category of apps, if the first category is single-app apps that can render on the server, the second category is really ambitious novel use cases. And two of my favorite ones are Meteor and Asana. So, have you all heard of Asana? It’s like a real-time app for task management.
CHUCK:
Yup.
AJ:
I have not, actually.
CHUCK:
It’s pretty cool.
AIMEE:
I haven’t either.
SPIKE:
It’s pretty neat. It was founded by early Facebook people. In fact one of the cofounders of Facebook, Dustin Moskovitz, he’s featured in The Social Network, [chuckles] Zuck’s roommate back in college. But basically, that’s the company that he founded with another early Facebook guy. And because they were richer than god, they could spend years developing this custom toolset. So, Dustin Moskovitz, he’s a billionaire. And so, they took that runway and they basically bet the farm on running JavaScript on the server. And they started doing this before Node.js came out, which is hard to believe. So, Node is really young. I think it came out 2010 or so. And so, before that the Asana team, they were working on just a precursor to Node called V8CGI which was the really naïve way to bind the V8 JavaScript engine with some HTTP stuff.
But long story short, they built this pretty sophisticated framework that allows them to do all this real-time, real fancy real-time syncing stuff and offline support and a lot of really neat stuff. So, they actually don’t do server rendering, which means that their app loads really, really slowly. But it enables this whole other approach at state management. And so, if I could try to describe it, basically they have for every single user session that they have in the browser they spin up another process on the server, which is crazy when you think about it. They built a custom HTTP router that was stateful. Normally we think of HTTP as stateless, right? So, all user requests, they can be bounced to any web server. It doesn’t matter. But they actually replicate, they keep the full state of the user session on the server.
So, as a user will click around and there’s JavaScript views triggering events and data is being fetched, it’ll synchronize those events with the server side. And the server will also fetch all that. And it maintains an exact copy of what the state looks like. And it’ll execute all the views and it just throws away the HTML. It doesn’t even look at the HTML that’s generated by the views because it’s just interested in having a perfect copy of the state on the server and the client. So, that’s a mindblowing approach to isomorphic JavaScript as well.
AJ:
So, I know that there are naysayers to isomorphic JavaScript. And I don’t know what it’s about. I just see the sarcasm Twitter stream from the horse accounts, especially the past week [Laughter]
AJ:
There’s been a ton of that.
SPIKE:
Yeah.
AJ:
Why? What’s the argument against it? What’s the downside to sharing code?
[Chuckles]
CHUCK:
So usually, when I hear people talking about isomorphic JavaScript I hear people talking about it like it’s Mecca. It’s, “Oh, it’s the only way to go. The cost of switching between my frontend and my backend because they’re both in JavaScript is so low.” And to be honest, I’m a Rails developer and I use Angular on the frontend. And I just don’t feel that huge barrier between the two. The other thing is that I’ve tried to use things like Meteor.
AJ:
Ugh.
CHUCK:
And a couple of the other isomorphic… or just MEAN stack. And there’s still a barrier because there’s a difference between the frontend and the backend. They just work differently. And so, you’re working in different worlds, frontend and backend. And so, yeah you can share some code. It’s usually your business logic. It’s saying if you put a phone number in here, it’s going to come out formatted properly. Or if you do a validation, it’s going to happen the same way on the frontend and the backend. And so yeah, some of that you can share. But for the most part, the frameworks look different because their concerns are different.
AJ:
Yeah.
CHUCK:
And so, I’m not a naysayer. I’m not against isomorphic JavaScript. I don’t see the tradeoffs as being a huge swing in the other direction either.
AJ:
Okay.
SPIKE:
Yeah. Yeah, I think that’s a good point. I think there are a few things to address there. The first is why is there so much hate about isomorphic? And I think that by and large it’s because of the word. I think a lot of people really…
CHUCK:
[Chuckles] That’s probably fair. [Laughs] It’s a dumb name.
SPIKE:
[Chuckles] For sure. I think that a lot of people really don’t like the name. And I bear some responsibility for that. I didn’t carry, I didn’t coin the term. I’ll deflect that over to Charlie Robbins and Nodejitsu and a blogpost he wrote in 2010. [Chuckles] But I think I’ve probably done more than most people to popularize the term. And so, there was just this past week, there was a blogpost by Michael Jackson who I think he’s affiliated with Ryan Florence, another Utah…
CHUCK:
Yeah, yeah.
SPIKE:
JavaScript developer. But he was advocating for the use of the term universal JavaScript. And that’s fine. Isomorphic, it’s just one of those words.
AJ:
So, you’re saying it gets hate because it’s like, “You tryin’ to talk to fancy, yo. Shut up.”
CHUCK:
I think for the most part people who react violently to it are the people who have been beat over the head with it. And so, they’re not reacting because it’s a bad idea. They’re just reacting because they’re tired of hearing about it.
AJ:
Okay.
SPIKE:
Totally.
AJ:
Okay.
SPIKE:
And then your second point was like, is it necessary? Are the concerns the same on the backend and frontend? So much depends on what your goals are and what the constraints are of whatever app you’re trying to build.
CHUCK:
That is very true.
SPIKE:
And there’s… I like to say that isomorphic JavaScript is a spectrum. And on the one side, on a really, really simple side, you can share just a few little bits of templates or some name-formatting code or date formatting or something, right? Underscore, just share Underscore. Whereas on the other side you can sync your entire application in run-time between client and server and that’s what Asana does. And that’s the most crazy, ambitious implementation I’ve heard of. And then you can fall anywhere in between as necessary for you. So, I think that’s [chuckles] important [39:48].
CHUCK:
Yeah. Yeah, I think some apps are probably going to be better suited to that than others. I also don’t think it solves an immediate pain for most app developers.
SPIKE:
I think you’d be surprised. It’s going to sneak up on you, whether or not you really realize it. We’re starting to see a lot of really big companies invest heavily in it. And I think that those are on the cutting edge. And I think most app developers to be honest won’t notice the difference for example in performance because it’s not a really performance-critical application. But you see, LinkedIn is about to redo their whole… so, Ember which is a famous framework that gets a lot of love and a lot of hate, they recently rebuilt their view layer to support a virtual DOM. So, Handlebars is being replaced with HTMLBars which is inspired by React. And it supports server rendering. And they’re branding it as FastBoot. They also hate the isomorphic term. But they’re doing it with FastBoot. And so, they’re very quietly embracing that.
And then there are some big companies, some big public companies. I don’t know if it’s totally public knowledge yet, but that are going to be rebuilding their whole stack on that. If you look at Yahoo, they totally rebuilt Yahoo Mail using isomorphic React, [isomorphic] Flux. If you look at Netflix, they’re embracing it. It turns out that in there, a lot of their apps… they have to build apps for weird devices like TVs and Heroku and all these things. But it turns out even on iOS and Android for the most part, it’s a web view, which is crazy to me. But it’s mostly a web app in there. And they’re actually looking at using React to do server-side rendering just so the load time is lower on their native apps. And what was the final example I wanted to use? Facebook is investing in isomorphic React. They’re rebuilding their mobile web app with it.
So, I think that it is out of reach or not a concern for your middle of the road app developer who’s mostly interested in shipping features, small team. But then once you have hundreds and thousands of developers and every 10 milliseconds is super critical to your success, then that’s when you see teams investing really heavily in it.
AJ:
Well, if you can get it for free with something like Rendr, why not use it now?
SPIKE:
[Chuckles] Amen. [Chuckles] Yeah. Or Ember even, yeah.
CHUCK:
Yeah.
AJ:
I hope that a similar tool comes out for Angular, because I’ve wanted that. But I think Angular 1 is probably too state-heavy for that to happen. It sounds like Angular 2 is a little bit more functional of a paradigm. So, maybe we’ll see that. Fingers crossed.
CHUCK:
Yeah, it’ll be interesting to see where things go. I have to say that I’m happy to be wrong on isomorphic JavaScript as I try it out in the future. But yeah, right now I’m just, I’m not sold.
SPIKE:
Well, good. [Chuckles]
AJ:
I’m definitely not a… I would never hold a gun to someone’s head and be like, “We’re doing this in the entire nation now.” [Chuckles]
SPIKE:
Yeah.
AJ:
Because I don’t think… so, the extreme that Meteor takes it, I don’t like it. But I’ve seen people use it where they have modules that are both in npm and in Bower, like the phone number validation, that kind of thing. I think it’s great.
CHUCK:
Yeah.
SPIKE:
Yeah.
CHUCK:
Alright, well anything else that we should cover on Rendr before we get to the picks?
SPIKE:
The last thing I’m going to mention is that we’re actually moving away from Rendr to a slightly different approach that’s similar. Because one reason is we’re ditching our separate mobile site which is all Node and we’re going towards responsive. And our new approach is with React. And we actually, we’re serving the page with Rails. But then underneath Rails there’s a little Node service that its only responsibility is to return HTML. So, we can serve and render our React components without the full Node stack.
AIMEE:
Is this Mystique that you were talking about in your talk?
SPIKE:
Oh, that is Mystique, yeah. So, we’ve called that service Mystique and it’s based on open source components. And maybe we’ll dive into that a bit more. But it basically allows us to keep Rails as the main HTTP serving app but then opt into rendering specific components on the server side.
CHUCK:
Alright, very cool. Well, I think a lot of that’s a topic for another day. But if people want to know more, if they want to ask you questions about it, how do they do that?
SPIKE:
Well, there’s Twitter. It’s always a good approach. My Twitter handle is @spikebrehm. And you can follow @airbnbnerds as well. It’s the engineering team. And that’s probably the easiest way.
CHUCK:
Alright. Well, let’s go ahead and get to the picks. AJ, do you have some picks for us?
AJ:
Oh, absolutely not.
AIMEE:
[Laughs] I can go if you want.
CHUCK:
Alright, go ahead.
AIMEE:
So, last week or because of the week prior I was on vacation. I was eating not the greatest food, not healthy anyway. I went for a really good barbeque and that was my pick last week. So, this week I’m going back to my normal diet. And I’m not only going back to my normal diet but I’m going to try paleo. So, I’ve been off and on with this before. But I started doing it while I was on vacation. And I felt amazing. So, my pick, non-programming pick this week is the paleo diet. You have probably heard of it. So, if not check it out. You’ll feel awesome if you do it.
Anyway, and then my second pick is another programming podcast, maybe not as good as JavaScript Jabber. But it’s called Programming Throwdown. The website for it just does not do it justice. It’s pretty awful. [Chuckles] But the podcast itself is pretty good. So, I would recommend listening to that. They just talk about… they have a bunch of different stuff. But each week they go through a different programming language. And I’ve just found it pretty interesting. And the guys on are somewhat entertaining. And that’s it for me.
CHUCK:
Yeah, the paleo diet’s almost as controversial as isomorphic JavaScript.
AIMEE:
[Chuckles] I really do feel incredible by doing it. I had all this free time when I was on vacation to cook all of my meals from scratch, like cut up fruits and vegetables and just eat a lot of good meat. And I just, I felt awesome. So, if you have the time to do that, it’s helpful. [Chuckles]
CHUCK:
Cool.
AJ:
It’s cool to feel connected to the food chain, too.
AIMEE:
[Chuckles]
AJ:
I bought, butchered and ate a rabbit a while ago.
AIMEE:
[Laughs]
AJ:
And it was really terrible, because as brash of a person as I am, taking life from something else to eat it, it was hard.
AIMEE:
[Laughs]
AJ:
But it gave me a lot of respect, you know?
AIMEE:
Poor thumper.
AJ:
It gave me… because I ate that rabbit and I looked in its eyes and I killed it.
AIMEE:
[Laughs]
AJ:
[Laughs] But I ate it. And it gave me a lot of respect for how we used to have to live back in the days of yore that I don’t know anything about.
AIMEE:
Well, I was more focused on the fruits and vegetables. But killing a rabbit and eating it’s probably good too, I guess. [Chuckles]
CHUCK:
[46:39] killed a bunny.
AIMEE:
Poor thumper. [Chuckles]
CHUCK:
Alright. I’ve got a couple of picks here, mainly just one. And it’s just something I’ve been thinking about for a little bit. So, it’s more free unsolicited advice [chuckles] than a pick.
AJ:
Yay. [Chuckles]
CHUCK:
[Chuckles] But I’m fairly involved in politics. I listen to a lot of folks out there on both sides of the aisle. And one thing that I notice is that a lot of people wind up shouting about the other side. And I really just want to encourage people to not miss out on the richness that people offer, especially the people who disagree with you. So, if you’re a republican go find a democrat and talk to them. And if you’re a democrat go find a republican. But also in code. If you’re a staunch, “We should always render on the server side,” and you want to go talk to somebody that says that it makes sense to render on the client side, go find out what those concerns are. Go have those conversations.
I’ve also had interesting conversations with people I vehemently disagree with on religious topics and other topics. And it’s helped me figure out where I’m at and what I care about and refine my thinking. It’s also helped me realized that I don’t always have the answers, even though sometimes I think, “Oh gee, well that’s kind of obvious.” Somebody has a different answer and it’s tightly held. And there’s a reasonable way that they got there. And there’s some premise that I just don’t agree with that would get you there. So, just take a minute and go talk to people that you don’t have something in common with or that you know you disagree with on something. And have a friendly but deep conversation about it. So yeah, so that’s my pick.
SPIKE:
Yeah, amen.
CHUCK:
And I honestly think that if we can actually do this and find a common ground, we could solve a lot of the issues that we have. Not all of them but a lot of them.
SPIKE:
Totally.
CHUCK:
Now AJ, does ‘I’m ready’ mean ‘I have picks’?
AJ:
Yeah, that’s what it means. That’s what it means.
CHUCK:
Okay. Why don’t you go ahead and give us some picks?
AJ:
I’m picking Chuck’s pick because I think it’s absolutely awesome. I hate walking on eggshells and I love it when people are just open and they share what they’re passionate about. And I learn because I come out with blanket statements. And then somebody else comes out and says, “Well actually, you’re wrong. Here’s why,” and some really good reasons. And I’m like, “Oh, cool.” [Chuckles]
SPIKE:
My pleasure. I’m just kidding. [Laughter]
AJ:
No, no. I’m glad. You explained it well. I saw your point of view and I get it. Yeah anyway, I’m going to churn on that a little bit more.
But SSH as a proxy, bet you didn’t know. There’s this thing called dynamic port forwarding. And so, if you’ve got say a Raspberry Pi that’s sitting inside your home that’s connected to your router, you can use SSH as a proxy. And I’m linking to a little article that I created on how to do it so that if you needed to access your router from home or if you were at some network where it was blocking the funny YouTube video you wanted to see, you can use Firefox and SSH to be able to visit any webpage through your home network.
And likewise, I was playing around with OpenVPN. And the purpose is I’m working on this home cloud system and I need a way for, like if you’re a student in an apartment complex or something like that or you’re taking it inside of an area where the network doesn’t allow dynamic router configuration, that you’d still be able to give public web access to some device. And so, I was able to figure out how to do that with OpenVPN. And I’m still… my article isn’t finished on it yet. Maybe it will be by the time this gets published, but maybe not. But I’m getting down that route. And so, I’m really excited about that, too.
CHUCK:
Alright. Spike, do you have some picks for us?
SPIKE:
Yeah, sure. You guys have broad interests. I have to maybe expand my scope a little bit. But one point on what you were saying earlier, I think that the answer is often “It depends.”
CHUCK:
Yeah.
SPIKE:
And that’s hard for people to accept.
Anyway, so my first pick is something called Alt. Alt, A-L-T. It is a Flux implementation. And Flux is part of… it’s closely related to React. It’s an application pattern for React. And Alt is one that was written by one of our engineers at Airbnb. It’s got quite a popular presence on open source. And it’s just a very nice one that is not a lot of boilerplate. And it also supports server rendering, if you’re interested in that kind of thing.
And I guess my second pick would be, I’ll get out of programming a bit, it’s a band I really like called Tame Impala. You may have heard of Tame Impala. They’re a…
AJ:
Yeah.
SPIKE:
[Chuckles] Australian psychedelic rock band. They kind of sound like The Beatles if The Beatles kept playing in the late 70s. But they’ve got a new record coming out soon. And it has a couple of really great singles that are just so good. They’re Australian, Australian band. And it’s just very refreshing if you like psych rock. So, that’s my second pick, Tame Impala.
AJ:
They also have a song about ES6. I’ll link for you.
SPIKE:
Is that right? [Laughter]
AIMEE:
Nice. [Chuckles]
SPIKE:
[Singing] Feels like we only go backwards, baby. [Laughter]
SPIKE:
Yeah.
CHUCK:
Awesome. I love it when our guests sing to us.
SPIKE:
I could sing this whole thing.
CHUCK:
There we go.
SPIKE:
Next time.
CHUCK:
Server side! Server… no, that’s death metal.
SPIKE:
[Chuckles]
CHUCK:
Anyway, alright. Well, let’s go ahead and wrap up the show. Thanks for coming and talking to us, Spike.
SPIKE:
Hey, thanks so much for having me. It was a pleasure. I like this format a lot. You guys are great.
CHUCK:
Alright. Well, we will go ahead and wrap up and we will catch everyone next week.
[Once again, this episode was sponsored by Braintree. So, go check them out at Braintree.com. If you need any kind of credit card processing or payment processing in general, they are a great way to go and we appreciate them sponsoring the show.]
[This episode is sponsored by MadGlory. You’ve been building software for a long time and sometimes it’s get a little overwhelming. Work piles up, hiring sucks, and it’s hard to get projects out the door. Check out MadGlory. They’re a small shop with experience shipping big products. They’re smart, dedicated, will augment your team and work as hard as you do. Find them online at MadGlory.com or on Twitter at MadGlory.]
[Hosting and bandwidth provided by the Blue Box Group. Check them out at Bluebox.net.]
[Bandwidth for this segment is provided by CacheFly, the world’s fastest CDN. Deliver your content fast with CacheFly. Visit CacheFly.com to learn more.]
[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.]