 Thanks for coming to Mustache in the Front, Mustache in the Rear. I know you had choices with the birthday suit. I lost my slides yesterday, so I'm apologize. My hard drive was encrypted. It was a bad move. And then it got, what do you call it, corrupted. Encrypted and corrupted. So on the plane I realized I had no slides. So I did all this on my iPad because my computer is unusable. Apologies. My name is Patrick Ewing. I was sent from the New York Knicks for about 10 years. Now I coach my ETH and write code at Twitter. So I'm the tech lead for the web client team and the team's changed a bit, but this is the team that built, these are the engineers that built New Twitter. Obviously there's a lot more people who contributed to it who couldn't make it on the slide, but it was a pretty small team, about 7 engineers. And it was a really awesome experience, I guess you could say. And also a really challenging one because the Twitter front end had remained pretty much unchanged since, I mean it had been iteratively changed since its inception, but it was still a Rails app with ERB templates and not a lot of, it had just sort of grown over time and something new was necessary. One thing I found when I, so again, yeah, like my handwriting is kind of weird and so I hope you guys enjoy that. When I first got to Twitter, rendering was actually one of our biggest problems, which is not something I expected. I expected something with the massive amount of scaling memcache or sharding databases, like these are all challenges, but at the time they were pretty much under control, but 12% of our CPU time was actually entirely used by rendering tweets. So when I say rendering is hard, I mean, I mean it that way, it's actually a lot of work to concat a huge complex template, and that was actually a huge problem. I also know it's hard because it's complex, like view code can get really squirrely, really fast. It's always the easiest place for people to like tack one more thing on or embed some business logic that goes untested because it's just view code and then later on ends up, you know, causing 404. So rendering is hard, and mustache is a lot of things. I was thinking, so that's, those are mustaches. Who in this room has used or played with mustache at all? Alright, so like about half of y'all. So the things I like about mustache are that it's simple, it's fast, and it's everywhere. I will, I'll go through what I mean by that. So the mustache is simple both as an idea and as an implementation. Chris Weinstreth modeled it off of C templates, and the idea is to have basically no logic or next to no logic in your view code as possible. So the entire templating syntax can pretty much be covered in two slides, which I'll do. It's also very simple, like pretty simple implementation. There's a pretty basic parser, and then, I mean, if you drill down enough, it's some regexes, right? It's not, it's not fancy. This is, this, so yeah, I'll just do a quick touch, like, run over of the syntax. Interpolation is done with double mustaches. You do template inclusion with greater than. And content is escaped by default. So you use the triple stash to when you want HTML unsafe characters. Then you've got sections. All sections use this hash syntax. So on the top, very basic conditional, we've all seen this before. You can enumerate over a collection, and we'll go into how mustache knows that it's a collection. And then you can drill down into other objects with this dereferencing thing. It all depends on the return, the type of object that's returned from the mustache view. We'll go into that. But that's basically all there is to it. There's really not a lot, there's not a lot to get hung up on. And I love, I love that fact. I love that there's no need to test my views anymore, because all the logic is elsewhere. And yeah, so that's pretty great. I also think the simplicity is what lends itself to making the thing really fast. This is a super technological graph that I made based on memory from the graph I originally had. It's pretty daunting, but benchmarks are very important and trustworthy, and you really can design your code around some hard data that you've gathered. So that's handle. It's pretty slow. ERB is also pretty slow. We found that mustache.RB was actually slightly slower than ERB, but as fast if you catch these view objects that it generates, I'll go next. It's basically comparable to ERB in Ruby. But then if you look at mustache.js on the right, it's actually faster than every jQuery UI and jQuery templating system I can find. It's blazingly fast. So that's interesting. So when I say mustache is everywhere, I mean that there's an implementation for pretty much any language that I know a programmer works in. That makes sense. I've seen Java, Scala, C++, PHP, Python, Ruby, JavaScript. It goes on and on. It's so simple to implement. I think people just kind of start doing it as an afterthought, and there's a pretty active community of people who are pushing these implementations forward. Oh, and it's also everywhere because we started using it at Twitter almost a year ago, first in little places. So if anyone remembers hovercards, some people love those, some people hated them, but those were mustaches rendered on the client. And that was the first place where we chose to use it. So in addition to ERB, which was rendering all the tweets, we were using mustache to render this like extra layer on top of tweets called hovercard. Then there was this at-anywhere project, which was a really cool way of extending Twitter into other websites. So you could like app names on other sites, or you could interact with them like you could within Twitter, right? Reply people, tweet at them. And these were hovercards that were, I'm sorry, these were mustaches that were rendered on other sites. Again, mustache.js. And then when it came to new Twitter, we were warming up to the idea so much and had really gotten used to it that we basically decided to do the entire thing in mustache. So this is like a big question, right? Everyone who's worked in Rails is really comfortable with the Rails view stack. And there's something that seems a little bit conceptually similar to me about returning a complete page and then updating it as needed with like little other bits in HTML. So why do we render on the client? And there's like so many reasons for and against this. I couldn't possibly go into them all. But we found a number of really good reasons as we developed this. So again, I want to say that this is really fast. It's fast for us for a number of reasons. We send much less data over the wire because we are just sending down the template once and then we're sending down just raw JSON data. And so this is like about halves what's coming down in transport. And JavaScript interpreters have gotten really, really fast. There's just so much research being done into making them speedy that like I showed you before with the computer science, it's just really like the fastest... I don't know, JavaScript is fast at sticking strings together. I don't know. It's remarkable. And we also find that it's really easy to share your view code when it's in this format because you could share across language boundaries. It was one of the most interesting things. Because the template is language agnostic and there's limitations across these different languages. If you have a clean API, you could do your rendering anywhere in theory. And we'll get more to how that actually... We'll get into how that works in practice. It's also great for an organization that reuses data objects and needs to display them in different contexts for you to basically be able to fetch views over HTTP. So someone who's building a micro app within the company could just pull down your view code because it's open source and sitting around on an HTTP endpoint and using this very small moustache.js library glom it together and be rendering the exact same HTML that you're rendering in Twitter.com. So that's cool. Another reason that we chose to do it came out of the Anywhere project. The Anywhere project yielded this thing called the JavaScript API. It was actually sort of like a spike that was not... I wouldn't say it's essential to what Anywhere did, but it was the work of a few people, primarily this guy, DSA. And it's this awesome, chainable way of accessing Twitter's REST API from JavaScript. So if anyone wants to play with this, there's still a preview version up. It unfortunately isn't finished publicly yet, but it's really powerful. And you'll see that what we're doing here is we've got an API object, we can find on it, and then we're just chaining calls, jQuery style, and then inside this callback, we're creating a moustache view. So that's the two parts of the moustache world are the template, which is that simple HTML or whatever with the basic moustache syntax and the view object. So that's like, you could compare it to a presenter. It's kind of just a data hash that's decorated with a few extra methods or functions for basically like a helper in Rails, you could compare it to that, but it encapsulates all of the data that you're going to be rendering in your view. So the view object knows how to render itself there, and this turns out to be pretty cool and really, really rapid for building a tour client, the JavaScript API lends itself to that. So then the question is, if rendering a JavaScript is so great and really who I think I am coming to RubyConf and telling you how awesome JavaScript is at rendering, are we done? Why not just do all of our apps on the client? We'll know. You can do that. For one thing, we want to maintain accessibility, and there still are something like 3% of internet users in the United States have JavaScript turned off. I think that's staggeringly high. It's weird that it's so high in the US. In Brazil, it's like 0.03. So I don't really know why the US still has so many people not using JavaScript, but then there's also just the matter of devices that don't support it at all, like screen readers, et cetera. We also need to send down the initial page. So if you've seen New Twitter, it comes down with the basic Chrome, and you can see that you're logged in in the upper, the top menu, and you've got... So we've got to render that server side. And we also do this thing... Oh, sorry. When I was talking about it being faster on the client, I should note that we did try rendering server side. First, we actually tried using V8 and SpiderMonkey on the server, which was a very interesting experiment. So it would be JavaScript on the... Mustache in the front, Mustache in the back, but it would be Mustache, JS in both places. We ended up not being able to do it just because maintaining old Twitter and New Twitter at the same time like we basically didn't have the capacity to add a new VM to the mix. It just wasn't what happened. So we need to render... Anyway, we need to render server side so that we can precede the cache. This means that we don't want to do an initial fetch when the page is loading. We don't want to load your whole page for you and then start fetching data from the API. So what we do instead is we use Mustache on the server to embed JSON in the page. So rather... We actually found that this is faster than rendering HTML on the server. So we had a Ruby... We had a Mustache Ruby view stack that could render all the same templates as Mustache JS, but it was actually faster to not do that and to instead basically just transform... just embed JSON as a string in the page body and then after that was sent down, the client would render it. So that was pretty interesting. And then lastly, you need to render server side for the Google. If you want the Google juice, then you need to be able to index your stuff. So if you've noticed the hashbang URLs in the New Twitter, we've added that kind of ugly little blemish, that's ultimately for the Google and for anyone who will be able to... basically so we can send them rendered content that they ask for that's not in JavaScript. So we do need to render on the server for them, for the bots. So this is what we ended up having. This was our view stack. Primarily Mustache JS, Mustache RV for rendering the initial layout and preceding the cache and for the Google bot and then these shared templates. Okay, so I'm just going to dig a little bit more into how this works and so that we can look at what does this mean to share a template? Right, so just a quick reminder, the template is the HTML string, a file living somewhere in your file system and available at a URL that contains text and the Mustache syntax. And then the view is an object. So if you're going to share... So basically you don't need an object to use Mustache, all you need is a hash. In Mustache RV and Mustache JS, you can pass it a data object and it will render it appropriately. But of course we know that APIs should usually not be in any way concerned with display and presentation logic, it should be data. So sometimes you can just render data directly to HTML, it's no big deal. Often you need to string format a date time, you need to dig into a user and just like combine their name in some fancy way. So what we've got here are two view objects. One in JavaScript and one in Ruby. Another kind of pseudocode, but this is roughly what you see in our view stack. We've got inheritance and we've got a methods block so that this base tweet shares the ability to refresh itself from the API and it modifies the data that's assigned to its instance variables. So it returns a Boolean for whether it's a top tweet or not and it uses our utility linkify function for rendering linked text. Over here we've got a stream tweet in the Ruby view stack. Here context is basically the original hash that you passed in that we got from Rails on the Ruby stack. So you can see, actually the first two are exactly the same, right? You can see that there's so little here that we need to do that it barely diverges from the JavaScript code. The last one I included just as an example of what if I don't want to give up all my nice Rails helpers? But we just include URL Rewriter in our views based class and then you can super to it with the user screen name to get the profile path for that user. The need for that is because Mustache has no methods, have no arguments, there's no chaining so if you want something to be displayed in your view you do need to create a function for exactly what you need. In this case you're just saying I'm always going to be pointing towards the user who wrote this tweet. That's the profile path. So those are, you know, this is some code duplication right here, right? Everyone's a little nervous. All right, good. And then this would be an example of a view. And I include this just to show you kind of like what a complex, somewhat complex Mustache template looks like. I'm sorry, yeah, this is the template. And a lot of people are probably like, half the crowd is probably, I'm guessing, really into this because it's code and it's a lot of code. It's all mixed up together. A lot of people are probably retching because it looks really ugly compared to a lot of other templating libraries. And I feel both of those. Yeah, there's still internal debates about the merits of this as opposed to like Hamel or things that other people sometimes fall in love with. Anyway, so if this was a partial inside, let's say that this, we were iterating over these and this is a, we're dereferencing a tweet object at the top. So we're saying everything inside here is going to be called on this tweet context. We do triple stash in the linkified text because it's already been HTML escaped and then linked, so at names are linked, hashtags are linked, et cetera. And then we dig into the user so the tweet has a sub object called user and then screen name references that. So it's not the screen name of the tweets on the user. We check that is top tweet Boolean. And then retweeters, we actually didn't have to modify our view object at all. Retweeters is returned to us from the JavaScript API. So that's innumerable and so for each of those retweeters we're getting the screen name of the retweeter. And that's it. Yeah. Mustache checks the type on the view. So I wish I could tell you at the top of my head what it does to check. I think it's just checking that it's an array. I don't think you, in Ruby Mustache it would be any innumerable. In JavaScript I believe it has to be an array. Or it could be a collection with that response to length. You're absolutely right. Yeah. And so I personally think that the hash syntax is a little overloaded. I don't see why you wouldn't. Because obviously you can't, this wouldn't mean much if retweeters was a single element, right? And there's no way of knowing from the template. It definitely pairs the template to the view object very tightly and it depends on the type return there. It's pretty loosey-goosey in that regard. But we also, we haven't had any trouble with that so far. The templates for us have remained pretty static. Mustache respects whitespace. Which is good because we often end up using it like in classes, like in attributes. In HTML attributes we'll end up doing Mustaches. Does this class render here, etc. And you need it to respect whitespace. Good question. If anyone wants to shout out questions, we could wait until the end, but we could also just go now. So I was going to discuss some drawbacks that we had. This was an interesting one. JavaScript and Ruby as we all know have different coding conventions. And it was getting the JavaScript programmers and the Ruby programmers at Twitter on the same page. There were a lot of polyglots, but basically this was really not what I expected. But one of the biggest problems we ran into was camel case versus snake case. Nobody wants to change their case. All of JavaScript and all of the DOM API and browsers is cannibalized. And everything in Ruby is snake case. And I think that whichever you used first, always seemed kind of right to you. And so if you're sharing a view template, you're often calling attributes right on your data format. So whichever convention you choose will end up really changing your API and defining a lot of things. So this is like, it actually kind of became an interesting that had a really bad compromise at the end and we called it camel snake. So if you, yeah, there's some really, really clever programmers on my team. And this one fella managed to basically in the JavaScript API rewrite all of the Twitter API attributes in camel case. So if you wanted it to be a JavaScript API for JavaScript programmers, so all your, you know, you should be able to write code the way you're used to doing it. But he also made, he also left the original variables accessible. You could dig into it like a data object and do that. So since we were sharing between Ruby and JavaScript and we basically, like we Ruby programmers were like, we'll use snake and we'll just, we'll reference the original snake variables. The problem is where does that, where does it stop? And when you're writing new functions in JavaScript to wrap this stuff, you start modifying or overloading the snake version instead of the camel version or you write a new function you only include the camel version and then who really wants two versions of all functions anyway and which one do you use at any given time? It became a wrap. And we actually had a, we had like a counter on our whiteboard. We're like all in a war room working on this thing for four months. And we had a counter days since bitten by the camel snake and it was like zero or negative one often. This, yeah, this would be any time you tried to call it one way and you'd find that the property was only available the other way. So we're actually pulling that out right now and standardizing on the camel. Another drawback was mustache has no internationalization support. This is very important for pretty much everybody in the room I think. So the option out of the box is you can just define functions for every English string in your app where you, yeah, that's horrible. So we wrote this understache I believe is what we called it which you can wrap. It's just another mustache tag. And mustache is actually very, we're surprised how easy it was to extend. So any string that you want or any block of text you can wrap understache and it's passed to Twitter's internationalization system. And it works. I'm sad to say we've not contributed this back to mustache.js just as soon as the bugs stop and the whales are at bay. We fully intend to. And then the last thing that you really need if you're going to do this approach where, you know, ideally your API is such that you don't have to do a lot of logic even in your view objects, right? You can just call the data properties and spit them out. And especially for the most important things like Boolean switches and the types of what you're enumerating over and what's... And mustache is fairly gracious about nils and empty strings. It usually just swallows errors. But if all, you can turn that off. But I actually kind of ended up liking that part of it. But if you want to have any sort of logic, and you will in your view objects, you need to have tests that test both against the same expectation. So the way that we manage this in the Twitter Text Library, or Twitter Text RV, Twitter Text JS, and I think people are forking us on GitHub and also porting it to other languages is we have a separate GitHub project called Twitter Text Conformance. And basically all that is a series of YAML files that state inputs and desired outputs. And all you do in your re-implementation is you write a small test harness that feeds the YAML files, which are broken down by what function they test, into the function that's tested in your library and assert that the output is valid. So you can just include it as it gets sub-modulable or something less frightening. And that tends to work pretty well. And I think that brings me to the end of this tale of... This tale? Yeah. Thanks.