Essentials • 58:10
SproutCore is an open source, platform-independent, Cocoa-inspired JavaScript framework for creating web applications that look and feel like Desktop applications. Learn how to combine SproutCore with HTML5's standard offline data storage technologies to deliver a first-class user experience and exceptional performance in your web application.
Speaker: Charles Jolley
Unlisted on Apple Developer site
Downloads from Apple
Transcript
This transcript was generated using Whisper, it may have transcription errors.
Good morning. How's everybody doing? Y'all have coffee recovering from last night? I'm still recovering from last night. So this is section 433. We're going to talk about building native look and feel web applications. And really, we're not going to talk very much today about building native looking applications because, right, that's pretty easy. If you've ever used any kind of CSS, you know much about CSS, you can make your apps on the web look native.
The hard thing is to create applications that feel like they're native applications, even though they're running in the web browser. So that's what we're going to really talk about today. My name is Charles Jolley. I'm a software architect with the new MobileMe. For the last couple years, I've been working on, along with a big group of people at MobileMe, creating the web applications that you saw demoed in the keynote. So we're going to talk a little bit about how we actually did that. And when we talk about creating native look applications on the web, what do we really mean? Well, what we're talking about doing is taking an application like this that looks fundamentally like a web page and seeing how we can make this look and feel more like this, right? iPhoto.
What would it take if we wanted to create something like iPhoto on the web? Is it even possible? Well, it is, and we're going to discuss how we do that in four sections today. We're going to talk about the architecture a little bit, and if you don't get anything else out of this talk today, the architecture is really what I hope you'll walk away with the most, because understanding how to structure these applications is really fundamental to making it possible to create something this great in the web browser. Once you get your head around that, we'll talk about a framework we've been using for the last couple of years to create these applications on the web, and then we'll actually build one of these applications, and then we'll talk a little bit about how you can go about deploying these, because the actual deployment methods that you use to put this onto the server varies significantly once you start dealing with this architecture.
So let's get started. So architecture. What do we really mean when we're talking about building a native look and feel application? How does that differ from a desktop or from a typical web application that you might see today? Well, I think it really comes in three pieces, right? First is we expect an immediate response. When you click on something, it should highlight. When you edit some text, it should be changed. When you drag something to a folder, it should be moved. You shouldn't have to wait on server round trips very often.
As much as possible, you want the user to immediately see the change that they've just made. The second thing is we want, and really connected with that first bit, is a rich interaction experience. You know, when the Mac first came out, The big word with the Mac was this concept called direct manipulation.
And what direct manipulation means is, you know, as a user, I should feel like I'm working directly with my data. And that's even more true today on the iPhone where you can actually touch your data, right? So the web is largely about filling out forms and hitting submit. It's about clicking on links.
But fundamentally, you're letting the server do the data for you. You're just filling out a form and telling the server what to do to your data. When we talk about direct manipulation, we want something, we want these drag and drop, you know, keyboard control, rich interactive experiences that let people feel really in control of their data. And finally, this is a really developing technology, but something we have to be ready for as web developers, and that's offline storage. When you're using an application and it starts to really feel like a desktop application, people expect to have access to their data immediately, and they're not going to be willing to wait while you try to download all of their data every single time they come back to your website.
Offline storage is just getting into the web browsers, right? Safari's just getting it. Firefox has had it for a little bit. We're still waiting for IE to get it, but they'll get it someday, right? So eventually, they're going to get all these offline storage capabilities, and we as web developers need applications that are capable of taking advantage of that to deliver this really immediate response. So how does a typical web application do with this?
Well, not very well, right? Because a typical web application follows this really basic model. You load a page, you click on a link, the web browser gets the server from the page, it displays it, you click on another link, goes back to the server, gets a page, you click on a link. That's the flow of the web.
Click, load, click, load, click, load. Clearly, this isn't doing a very good job of getting us to this web application experience, right? Document-driven apps rarely have immediate response. You're almost always waiting on a server round trip. They never have rich interactions. You can't do drag and drop or anything like that. And they clearly don't have offline mode because everything interesting is happening in the server. So obviously, Web 1.0 model doesn't work very well. So people say, well, we've got a solution for that, right? It's this Web 2.0 technology. It's called AJAX. AJAX makes it possible.
We can build desktop apps on the web. And it's true, it's an enabling technology, but the way most people use AJAX today in reality still doesn't get us there, because the way people use AJAX today is something that I call 3270 AJAX. And the 3270 refers to a terminal that was actually produced by IBM in the 1970s. This is what it looks like. And now this terminal was revolutionary, okay? You have to understand something about the way mainframes worked.
Mainframes, for a long time, the way they worked is you type some text, type in a command, you hit return. It goes back to the mainframe. The mainframe sends an entirely new screen back to the terminal, and it repaints it. You type some more commands, it goes back to the mainframe. The mainframe sends back an entirely new screen, and it repaints it. It sounds familiar. It's just like the Web 1.0. The 3270 revolutionized the terminal because now the mainframe, instead of sending back an entire screen, could say, here's just a little piece of the screen I want you to repaint, right? So that made these terminal applications feel rich and interactive. Well, not really, but it got it a little bit closer. And that's the way most people today build AJAX applications.
It's fundamentally the same model. You load a page, you click on a link, it goes back to the server, it gets a page fragment, it replaces a portion of the page. Definitely better than the simple 1.0 model with document-driven applications, but it still doesn't really get us there. You get some immediate response. You do occasionally. Maybe you have a div that you've hidden and the user clicks a link and it shows right away. That's great.
You do sometimes get immediate response. Occasionally, sometimes you're able to do some drag and drop or something that gives a little bit more of that rich interaction. but even drag and drop, which people have been doing for years on the web, is still relatively uncommon in the web browser. And of course, offline mode still very rarely happens. There are a few demo applications out there.
Google Gmail uses it occasionally, but offline storage really is very difficult to do with 3270 AJAX because everything interesting is still happening in the server. The way people build AJAX apps today has extended the web 1.0 model, but it still doesn't really get us to building a native application. So how do we do it? Well, on the, or rather, let's talk about for a second, actually, why we can't get any further than that, because what a lot of developers, people will say is, well, you know, we really can't do any better than 3270 AJAX. And these are the reasons why they'll say. They'll say, you know, computers are just too slow. My server is way faster than your PC or your Mac could ever be. Computers are just too slow. And even if they were fast enough, JavaScript is too slow. I mean, really, have you ever tried writing any kind of factorial functions in JavaScript? It's horrible. You can't do it. And then the web, HTML, it's just too restricted. All I can do is boxes and shapes. I can't do any kinds of fancy graphics. It's hard for me to do other things without resorting to Flash. I can't get this really rich experience. But, you know, the reality is anybody who's thinking that way, you know, that was true maybe three years ago. Today it's not anymore. The reality is most client computers, most Macs and PCs that people use are as fast today as the fastest servers were two years ago.
Most of your customers in aggregate are using way more computer power than you could ever supply with your own servers. And on top of that, JavaScript is getting way faster. I mean, they're two to three times faster than Firefox. This brand new stuff coming with Safari, I mean, it's just screaming fast and IE's going to get it, okay? They're going to get it. So JavaScript's getting a lot faster. And, you know, as far as effects, have you seen Safari lately? If you've gone to any of the presentations, we have some incredible things coming along with CSS transforms and animations and drop shadows. And SVG finally coming. SVG are kind of a vector graphics language built right into all of the major browsers now.
So the reality is we can do it. When we couldn't, maybe three years ago. So if we could build a really desktop-like application in the web, how would we do it? Well, it's with a model that I call Web Client Server. And Web Client Server is based on the way the desktop does it. So how do we build rich applications on the desktop? Well, all of us use client servers today, right? If you use Apple Mail. You open Apple Mail, everything runs on your machine, everything's happening right there on your computer. You interact with Apple Mail. When Apple Mail needs to get some email or when it needs to send some email, it will go talk to a server as needed. But the point is, it's not driven by the server. Interesting things are happening in the client. And that's the real architectural shift that needs to happen if you want to build this on the web. So we can do this on the web today. We can instead of, the only difference is, instead of having these applications installed on our machines, we can take advantage of all of these powerful new features that are in web browsers and simply download clients right into the web browser. If you design it properly, you can even use caching headers and things so that once it's downloaded one time, it's generally going to be in the user's web browser and you get some really fast, really great experiences that happen in the web browser because it's the same model as what you use with the client server. The user interacts with your client. They never see you talking to the server. It all happens in the back end. And if you really go far enough in that direction, you can create something that's really, really rich and interactive. So some of the things that really make this different, of course, and I just want to kind of point out, really reemphasize the key difference here between what a 3270 AJAX model is that interesting things are happening in the browser. And that's a very, very important thing, that the actual application is running in the browser.
instead of dealing with emails on the server and just sending HTML fragments, the web browser knows what an email is or a photo or a contact or whatever you're building. It knows what those things are and how to do things, so it doesn't have to wait on the server to send any of that logic back to it. And you'd be surprised how much of that you can put into the web browser and still make a really exciting application out of it. So just to kind of review, document-driven model, everything's happening in the server, right? Click send, click send. 3270 model, it's a little bit better because we're only reloading parts of the page, but it's still fundamentally click send, click send. How does this work with the new web client server model? Well, you load the page and then the user interacts with it and that's it. They don't load another page, they don't do anything else. Whenever the client needs to talk to the back end, it can, but it's not necessarily required in order for the user to work with your application. Incidentally, this means offline mode is super easy to do because you've already built your application separated from the server. You just have to adopt the right syncing model with your server.
So how does this compare? Well, obviously everything's happening in the browser. You can almost always give an immediate response. You rarely have to wait on a server round trip. You can implement really rich, dynamic, interactive experiences. You can give the user back the direct manipulation that we lost with the web. And of course, you can implement client-side storage extremely easily, and you can have this complete offline mode capable, depending on how you built your applications. So that's the web client server architecture.
Now, if we built an application like this, or if we've adopted this new model, how can we build one very easily? Well, it turns out that for the last couple years, we've been using a framework that helps us do this. And when we started working, this framework is open source. We brought it in from the outside, but we've been developing it at Apple. And when we started thinking about this framework, we thought, what would a web client framework really need to provide for us? And, you know, we thought of really four important things. First of all, obviously a framework needs to provide a lot of common application functions for free. A lot of this rich interaction I talked about, it should just happen, right? Drag and drop shouldn't be that hard to do. Having keyboard control, having data side or client side models, all of that should be handled for us. Of course, it needs to be optimized across all web browsers so you don't spend your time dealing with why IE doesn't behave exactly the same way as Firefox or Safari. It should handle most of that for you. It should, any good framework would really eliminate a lot of the glue code for us, of course. You really don't want to spend a lot of time trying to snap together pieces of your application. You want to spend it writing features. And, of course, it needs to make coding a lot more fun. And, you know, on the desktop, we have something like that. Apple happens to be one of the people behind it, and it's called Cocoa. We thought, what if we could get something really similar to that? And so that's fundamentally what we built, and it's called SproutCore. SproutCore is a JavaScript application framework for the web. It has a lot of the same things that you would expect to find in Cocoa. It's a full MVSA framework. That means it's built on model views and controllers, just like all of the other popular kids are doing, right, with Rails and Cocoa, of course. It has a lot of the common features that you really love about Cocoa. One of the key ones is bindings and key value observing. And, you know, of course, lots of view controls and drag-and-drops and delegate patterns. It embraces JavaScript, which I want to talk about in a second, and runs in all these browsers. But I just want to talk really quickly about bindings. You know, the really cool thing about working with SproutCore is bindings just came along with Cocoa a few years ago. And so most of the API that you use with Cocoa today is actually built without bindings. In fact, most of the controls in Cocoa have almost two APIs. They have a bindings-based API, and they have a non-bindings based API. Well, SproutCore has bindings from day one. So we haven't tried to clone Cocoa exactly with this. What we've done is instead decided, we want to create a framework that would take these best features, but what if we had bindings from the very beginning? It turns out you can eliminate huge chunks of your framework simply because you can do this, what's called state-based programming using bindings. And of course, we're embracing JavaScript. So we're not going to try to copy Cocoa or copy Objective-C.
And I just want to take a second to talk about that because, you know, a lot of people, when they first hear about SproutCore, say, well, you know, JavaScript, okay, so maybe you've made a framework for it, but JavaScript's just no fun, right? It's not any good. It's kind of a toy language. And I just want to point out some things about JavaScript that maybe you don't know.
JavaScript is great, okay? It's a really great language. It has some big mistakes, in it that make it harder to use occasionally. The primary thing I think is challenging about it is it's such a forgiving language that most people start writing JavaScript and they pretend it's Java or C or whatever they're used to, and then eventually it doesn't do what they expect it to and they get angry with it. But the reality is JavaScript has some really amazing features that have been in some really advanced languages for a long time like late binding, which is what makes Cocoa so great. It is a hackable object model. Every object in JavaScript is just a hash. You can add properties to it any time you want. You can delete properties any time you want at runtime. That's extremely powerful. It has closures and lambda functions. That's what makes Lisp so great. Not the syntax, but the lambdas and closures are amazing, and they're actually in JavaScript, right? So, Coco's getting this with the next release in Snow Leopard, but the big difference between JavaScript and all of these other languages that I mentioned, including some others like Ruby and Python, is that it is the most widely deployed language other than C on any platform. It's on virtually every computer in the world today. JavaScript is everywhere and it has these incredibly powerful super productive features in it that most people don't even know is really there because it's hidden behind this Java-like syntax. So once you really learn how to embrace JavaScript for what it's really good at and start building applications based on that, you find that it's actually an incredibly enjoyable framework to work -- enjoyable language to work with. And building frameworks within it is really, really amazing. So with that, let's get straight to showing you a demo. So I'm going to show you a little bit about what you can actually accomplish with this.
So before we get to SproutCore, let's just compare this with the current state of the art. Now, Flickr is an extremely advanced AJAX application, 3270 style. So I'm on my page here with a couple of sets. Let's say I want to come in here and change this name. Well, how do I do that? Well, I can click on Edit, and I have to go into another page. And then this happened in 2006, so I want to add that. Well, that didn't actually change it. If I come back here, oh, well, I guess I actually have to tell the server to do it. So I wait.
Okay. I changed. So not bad. But still, everything interesting is happening in the web browser, right? So what happens if I want to say create a new set and maybe move a few of these photos from a party we went to to another page? Well, first thing I have to do is come back here and actually let's see here.
in a different location. Come here to Sets. I click Create a New Set. go to my new set. Now they do have some drag and drop, which is great. That's something that Flickr is known for, their advanced API. Of course, I can't directly manipulate the data in my other set, right? Because these are basically happening in the web server. So what I have to do is down here they show me all of my photos, and I have about 200 of them on here. So I'm going to have to slide through here until I can find the photos that I want. They do have multiple select, which is nice. And that goes ahead and adds some of them. Just drag that last one up there. Okay.
call this the big party. Of course, this hasn't actually changed anything. If I come back here to sets, again, it will make me cancel that. So I'm going to go ahead and save that. Now wait on the server. And there we go again. So not bad. It's a fairly fluid experience. But we're still looking at this, you know, fundamentally everything is happening in the web server. And most of the time I'm just looking at a representation of my data. So what could we do if we built this with SproutCore? Well, I'm going to show you this is just a little demo we built. This is available on the SproutCore website. And this is Photos. So Photos has a bunch of albums here. These are just loading from the server. Here's a few big ones.
You can see this one has actually 150 photos. And SproutCore has incremental rendering built in, which is the same thing Cocoa uses so you can draw a large amount of sets. We actually have done tests with this. I've had 5,000 photos loading here and it loads in about five seconds. So that's actually faster than iPhoto was a couple years ago. So let's say we wanted to -- well, we were going to do a couple things. Let's say I wanted to rename this to -- looks like I've got a selection bug there. Ignore the man behind the curtain. So we'll just see what does it take to actually change this to Canes 2006. I just click on it, type 2006 and hit return. Done. Maybe I want to select a couple-- well, actually, let's go ahead and add a new set. Just come down here, I'll create a new set. Call it the big party.
We need to add a couple things to this. So I can select these, I can command select them, I can shift select, I can hold the wrong key, I can shift select them if I want to. Of course, I can also use keyboard control. So it's all very natural. And if I want to add it, I just go, that's it. I just added them. Didn't have to wait on anything.
So of course that makes using this app is way faster. I mean, you're never waiting on the server. You wouldn't even know that this was happening in the server. In fact, a lot of what's going on in the background here, this can be communicating with the server to update your photos. It's also actually writing these changes to local storage if you're in the right version of Safari, just as you go. So you never have to wait on any of it. And of course, we can do a lot more with this, right? We can have a slider. Isn't that nice? It's really interactive. Works pretty well if you have a large number of photos even, even though -- and by the way, I've spent like a day on this guy, so if you really want to be impressed, buy MobileMe in a few weeks. So, and, you know, the other thing I mentioned was Safari has some really cool effects that they're doing, and so why don't we come over here, and let's just see if we go ahead and added -- It's here, there we go. If we go ahead and I'm just gonna show all these photos and we're gonna do select all, And, okay, so what can we do with this? Well, here's a little editor I've done.
Just a few things. One thing you'll notice is the titles are automatically selected and joined here because we're using bindings. It just noticed that we have multiple ones. So if I just instead select one here, I can actually edit it and say, say this guy was in Prague. That's all I have to do. It's done now. But let's do some more interesting things. So the new Safari-- which I just realized we just reset, and you're not gonna see this. So I tell you what, we're gonna download WebKit in the background while I show you some other amazing things. Okay.
So just pretend that didn't happen. So what happens if, let's say we want to, Let's say we wanted to reorder these guys over here. Now, there was actually no really obvious way to do that in Flickr. Here, it's really easy. You just grab it and drag it around. That's all you have to do. I can actually do the same thing with my photo library. I can just select a couple of these guys, and let's say I want to move them down. You can see the little highlighter. And we've actually implemented scrolling as you hit these edges, which, believe it or not, is extremely complicated in the web. and we just let go and it drops them. I'll show you, move these up so it's a little easier to tell.
Okay, so it's even awesomer in WebKit, so let me show you WebKit really quick. Notice how fast this is loading. Just keep that in mind. Stuff that in your back pocket for a little later. OK, so let's go ahead. I'm going to create the big party. since we're running in a different browser now. And I'm just going to grab a couple of these photos so you can kind of see this. Okay, so as I was saying before, I'm going to get these a little bigger so you can see this. So one of the cool things we have in WebKit is this thing called CSS rotation, which lets you rotate photos. So what happens if we can actually rotate photos in the web, right? It's pretty amazing.
But that's not the cool part. The cool part is that this is data living in the client. So what I did here was I have a slider that is bound to the rotation property on a controller that's managing all of these photos. And these photos actually live in some other albums. Remember, I just pulled them over from the other albums. So you see they're already rotated there too.
So, everything's pretty much handled for you. So, that's the demo. Now, something I want to point out about this, you saw how fast this was loading and everything. So, you know, we got a little bit of press with SproutCore on Monday. It was mentioned on some websites after the MobileMe thing. And so, this is running on the public SproutCore site.
And this site currently is hitting about, it's getting 5,000 to 6,000 hits a day, which is pretty high compared to what it's normally been getting, considering that it's running on a 995 shared plan from DreamHost. And so that performance is happening on a shared plan on DreamHost, which is huge, right? Imagine what you can get. I'll give you an example. I launched a web company a couple years ago. We got on TechCrunch. that's how we got mentioned here. We got on TechCrunch with my previous company, and we had a server, you know, very best server we could get. It was hot off the presses. It was running custom software up and down, and that mention on TechCrunch nearly brought us to our knees, right? This guy is running on a shared plan, and it's running smoothly because everything's happening in the web browser, and it's so efficient at being able to spread out the load across all of your clients. So you get not only some really great features, but even a little more difficult to appreciate. Incredible amounts of distribution of your application load, which just, you know, it does wonders for easing those sleepless nights when you just put your product out on the market. So there you go.
So that's our demo for now. Thank you. So that's SproutCore. There are a lot of really amazing things possible with this. Like I said, you'll see a lot more. There's some apps out, but there's even more coming. This is a demo app. Excuse me, a couple things I wanna just tell you about this. SproutCore is open source, as I mentioned. It's available with an MIT license, so it's extremely liberal. If you want to install it and try playing with it, it's actually distributed using the Ruby gem system, which is pre-installed on every Mac. That's why we do it this way. It uses Ruby for some build tools. You don't need any Ruby in production.
This is just to make it really easy for you to work with. So if you want to try using SproutCore, just do sudo gem install SproutCore, and that's it. You'll have everything you need to start working on a SproutCore application. If you want to learn more about it, there is documentation online, and there are some tutorials that are developing online at SproutCore.com. That was the site I showed you. You can also click on demos and go try out that application yourself. Works amazingly well even at a cafe. And just keep in mind when you're using it, that's optimized for loading photos, and I've spent about a day on it. So it's a pretty big improvement. So that's what you can get with your end product. Let's talk a little bit about how you would actually do this. So there are four basic steps to building a SproutCore application.
First, you want to create a new project. That's using the build tools that you would install with Ruby gems. And that's going to give you all your basic concept models that you need. You can then create your basic data models and views. Up until this point now, everything's going to be running in the web browser, so you don't have to actually even work with the server just yet. Write all of your controllers to bind everything together. So this is typical model view controller stuff, right? You design your model, design your views, tie everything together with a few controllers and bindings in the middle. And then finally, you can write a little code to send data back and forth from your server and your client. But notice that that's the last step that you do. And that's really important because it means if you have a team that's working, you can actually have people writing applications that run in the web browser and somebody working on the server. And even if they're not both ready just yet, they can continue development independently, which does wonders for delivering code in a shorter time period and makes your life a lot easier. But that's also a very involved topic. So we're not going to talk about that today. We're just going to cover these first three steps so you can get a sense of what it's like to build one of these apps. So step one, how do you create a new project?
Well, all you have to do after you install sudo gem install SproutCore, open your terminal and type SproutCore and the name of your project. In this case, we're going to build a converter app. And that's going to create some files for you automatically. This is a project. Now, a project contains a client's directory, which basically is all of the applications you'd want to use for this project. Maybe you just have one, a converter, photos. You can have as many as you want on a single website. You also have a directory called, actually, let me work from the bottom up. So you have a config file at the bottom that you use to manage a development server and your build tools. Then you have this directory called frameworks. SproutCore, you know, one of the more difficult things with building web applications is it's really hard to manage all of these shared libraries that you might use, like jQuery or Prototype or SproutCore in this case.
So SproutCore includes a build system that actually can manage all of these dependencies for you. If you wanna have a framework that you've written that's shared between all your clients, you just drop it into this directory and it'll be automatically included. SproutCore and Prototype are both packaged. We'll be adding some other libraries as well that you can just basically link into them it will automatically take care of packaging them and preparing them for your build, for deployment. It's really nice. Your application code goes in here.
So let's look inside the actual application. Now, there's a couple things you want to see. If you're, you know, model view controller world, you'll see three very familiar folders. You put your controllers and models and views in those folders. You can actually put them anywhere you want, and the system will take care of it. This just makes it easier. You have a file called core.js where you define your namespace. Sprout core helps you namespace everything so you can have multiple modules loaded at one time, and it will all work. You also have a main function where your main function goes. There are a few other things. This is the English Lproj. If you've done Cocoa development, you recognize that Lproj. SproutCore has built-in support for localization. So you can put your HTML, any images you want, any CSS. If you have localized JavaScript, in this example we have a strings.js.
You drop them into this English.lproj. If you want to do a French localization, you create a directory called French Elproj, and you just add whatever resources you want to have different from the English version. So you might have a different strings.js, for example, so you can localize your strings. And you can localize in any language. Sprout Core has built-in support for these four, but if you wanted to do anything else, you just use the two-letter language code.Elproj.
Sprout Core will automatically build and deploy it for you. So MobileMe is localized because we're Apple and we have to do that, and you'll see it's all actually produced using this system automatically. So it's a really, really nice way to handle localization, which is generally pretty difficult. We also have a couple extra little features. One of them is fixture data. SproutCore actually supports fixtures. You can load fake model data in here, like photos, for example. When I first wrote this app and I didn't want to pull it from the server just yet, I just write up a fake photo JSON feed and I drop it into fixtures and when I'm in development mode it's automatically loaded and installed for you. So you can work in fixtures without having any server mode. You also have unit testing built right in, which is huge because JavaScript is extremely difficult to unit test unless you're writing in SproutCore and then it's And now my colleague Peter is going to come up, Peter Bergstrom, and show you how to build one of these. Thank you.
All right, so we're going to build the temperature converter application that Charles just went over a little bit. So the first thing we're going to do is bring up terminal and use the SproutCore build tools to create our converter application. So this just builds the skeleton of the application actually.
And this looks familiar from the slides. And this is what we're going to modify. So let's go into the converter application and start SEServer. here, we can take a look at what it builds. This is just the generic page that we start with. But let's actually make this do something. So we go into the body RHTML here, and we're going to change this to font size. Let's see how we do that. Command plus.
Is that better? All right. OK. So let's do this. I'm just going to drop this in here. So now we have some HTML. And we use the Ruby helpers here to create a text field. It's going to be a text field view. And we're going to name this one Celsius. We can give it a hint. So that'll just be ghost text that will show up in the text field. here for Fahrenheit. I'm going to drop in some CSS as well. There it is. Adding 20 pixels, add a border.
So we'll refresh this. And now you can see here that we have ghost text. When we actually focus into the field, it'll change. And I noticed that I didn't change this. There we go. And the next thing we want to do is actually create a controller so we can put our application logic in there. So I'm going to go back in here.
we do scgen to build the controller. It's going to be controller. We're going to call it the-- convert controller. So this actually will create a controllers directory and a test directory. We'll get back to a unit test later. But the first thing we want to do is add some values here in the controller, one for f value, which is going to be the Fahrenheit value, and one for the Celsius value. And we can go back to our text field here and create a binding. So the binding will allow us to bind the value of the text field to the one in the controller. So if we do a change to the controller, it will update automatically and the other way around as well.
Fahrenheit value there. So now you see that it says 2 and 32. Those are the values we put in the controller. to bring up the error console. And you can see here that we can actually set the value of, for example, the C value to 300. it'll change. So if we do this without using set, we won't actually get a notification, so it actually won't change. So we need to use set to actually let everyone who's listening to the value that it's changed. So let's go back to the-- controller, we're going to create two functions here, one to convert from Celsius to Fahrenheit and one to convert the other way. So the first one is going to be convert C to F. And then And this is actually going to be a function that observes the value. So when we change the value in the text field, this function will be automatically executed. So we're going to do observes cvalue. So we're going to get the value.
our conversion. Here, so it's going to be 9/5 plus 32. And we're going to get the original Fahrenheit value. And since it's a floating point number, we can't just do a direct comparison and see if it's actually changed. So we're going to do math absolute rig minus converted. So just see if it's changed. And if it has changed enough, we're going to set the f value here to the converted value. And I'm just going to drop in the other function here.
So we should be able to now change the value here. So as I'm typing, the Fahrenheit value is changing. So now we actually have a working converter. But we don't really know if it works right. So let's build some unit tests. So when I created the controller, we actually also had a basic unit test created for us. So let's do some modifications here. So it should convert Celsius to Fahrenheit.
So I'm going to set the Celsius value. to something we know, 100. And then we can do converter, convert controller. get the Fahrenheit value, because it's already supposedly changed, and we can do "should equal" And now we can bring this up in the unit test suite. And you see that our test passed. Another thing that's really great is that we can turn on continuous integration. So this will run now in the background. And I can just leave this minimized and create another test here. So I'm going to grab this one.
Save it. And whoops, I actually did something wrong here. So I actually caused a unit test to fail because I tried to set it to 100 degrees Fahrenheit. That's not 212 degrees Celsius. So it actually is 37.7. So that failed. So let's fix this. tests. And now it shows that both of them have passed.
Thanks a lot. I think I set my -- this is why I write code and don't do logistics. So that's how you build a SproutCore application. There's another little feature that you can find actually documentation on the website. We have built-in documentation generation. So if you saw in some of the code there, there were some comments that it said, place your documentation here. You can put that in there and then just visit, just like there is a built-in test runner, there's also a built-in documentation viewer that comes with every application. You don't have to do anything, you just add, dash docs to the end of your app name, and you've got your docs. So if you're working on a big team, you really want to document your code and test it. So, okay, so some things that you want to do, just kind of review. Use SproutCore tool to create a document, create a project. The sc-gen tool contains generators that will create all the template code you need for models, views, and controllers.
So you can, and it automatically creates tests. It's there to help you do things in the best way without having to remember how to do that. And you can keep your views in our HTML template files. The HTML that was generated there actually creates both JavaScript and HTML for you and makes sure that they're bound together in a way that's progressively enhanced. So it's all done in the best practice kind of way. The other interesting thing about the way Peter built that app that I think is actually one of the most exciting things about how you build applications when you have bindings from the beginning, is you can keep all of your logic in isolated objects. So all of his controller logic only worked with properties defined on the controller. And then the controller was bound to the rest of the application. But when you want to do unit testing in user interfaces, that's typically very difficult. If you can isolate your modules in that way, it not only makes your code a lot more maintainable, but it makes testing just a breeze, just really easy to do. And finally, key to that is to hook everything together with bindings. So that's the application.
So great, we built an app. Now we're ready to launch our Super Converter 2.0 to the world. How do we get it up onto the servers? Well, most web servers, you'd actually want to create a backend service. Today, we're not going to talk about that. You do backend services with SproutCore exactly like you currently do if you use Java, if you use Rails, if you use PHP. Everything works.
It doesn't matter because your web application is already loaded and talking to it. How do you actually load your web application? Well, you use Apache or Lighty or any kind of web server that you want because all of your files are static HTML, JavaScript, and CSS. This is a really big change. This means that when you go visit someone's application, you actually don't have to wait for their, you know, huge, expensive application server infrastructure to activate. They can just shoot you back the HTML, JavaScript, CSS, get your experience up and running, and then make one request to get the JSON from their back-end service. So it's actually a lot lighter weight for your server that you built, the ones that are really expensive. The other thing that's really cool about this is that you can use content distribution networks. So we've used that before. to give us basically instant global fast access to all of the applications. We can just have them deployed on a content distribution network like Akamai or something like that, or Squid. And you can have those spread all over the world and you get instant global acceleration for an extraordinarily low cost. And you get all of this with one little command. It's called scbuild. And what scbuild does is it takes your source application that looks a lot like this, and it produces a bundle just like in Cocoa that looks like this. And what you'll see in this directory is four different languages have been built. They've all been converted to two-letter codes. And inside of that, you'll see a JavaScript.js, which is all of the JavaScript you need for that application put together, minified so that it can be delivered over the web with the maximum performance. Style sheets, all of your CSS files that we have, you can have as many little CSS fragments as you want. They're all combined together. All of your index, RHTML, which can be fragments, again, as many as you want, they're all put together automatically for you in this bundle that's ready for you to do an optimized load. If you want to visit one of these URLs, one of these apps now in a specific language, you would just drop this into your web server there in the Apache, and then you would visit, you know, say converter slash EN or FRDE. And I'm actually going to go back a slide here, and you'll see there's another index.html down there. This is essentially your default language, so if you just go to /converter, it will automatically load the English version for you. So you get this really nice, natural, localized behavior, and you don't really have to do much with it. And we built this great app, and I think we're gonna launch it and turn it into the next big thing on Facebook or whatever, so we'll have Peter come up and build the converter app.
So building this before was really difficult, but since Charles has done a lot of work on the build tools, it's been a lot more simple now. So now we just do sc build. converter, and we want to put some options here. So R will make it only build the required things like SproutCore and Prototype, as well as the Converter app. And we'll make this verbose so we can see what's going on. So it'll build Prototype, SproutCore, collect all the images, and also our little very small app compared to everything else. So it creates it in the temp directory. So let's go inside there. And just open that up.
So these are the things that are created, the converter application and the prototype and SproutCore. So inside of here, you can actually see that our index.html here, the text fields or text field views that we did in Ruby have now turned into input fields. And there's the -- here are the bindings and the hints that we specified for it. So basically all the things that we do inside of the RHTML with the Ruby help will actually be automatically converted into JavaScript for us so we don't actually have to do anything with it. And here's our minified code. It's not very large. And you can actually just go in here and this is what Sprockware looks like, minified as well. Now what we want to do is take this and drop this into our web server. here, and we can just go to this. to local host, converter, or static convert, oh, and auto completed.
So this is our wonderful deployed app. And it just works the same way as the one that we ran in the build environment. But this is a lot faster to load because we don't have to generate any of the JavaScript or the files in real time like we do in the development environment. So thank you.
So that's what it takes to do deployment. It seems really simple, and it is, and that's really important because typically deploying web apps, if you've not done that before, is a very involved process. This literally involves having something that copies a few things to your web server, and then you basically have no load. That's the reason why we're able to do something like the photos demo off of a shared server somewhere. So, you know, launch your next media empire on DreamHost. So a few deployment hints. Use compression. Now something you may have noticed if you've done much JavaScript before that we minify our JavaScript but we don't obfuscate it. And obfuscating basically means that we take all of your really long variable names that are descriptive and easy to remember -- not easy to remember but easy to read and it's converted into little F0 underscore or something like that. And there are two reasons a lot of people do that. One is they think it somehow protects their code which it really doesn't because you can deobfuscate fairly easily with tools built into TextMate, for example. And the other reason is because they think, well, I'm going to make my JavaScript as small as possible. But here's a really interesting thing. Gzip, which is the compression formula used by all web browsers, web servers when they deliver content, does practically the same thing as obfuscation. It's just better at it. So we ran some tests on this.
And what we found was if you obfuscate your JavaScript, not only will it not get any smaller if you're using Gzip, but it will actually sometimes be a little bit bigger because Gzip can no longer -- can't compress it anymore, but it does still have all that overhead of actually being a Gzip file. So we don't compress your code because -- or we don't obfuscate your code because it really doesn't get you any benefits. It does give you the huge headache of not being able to tell what your own code is doing if you have a bug in production. So it's way, way easier to debug minified code than obfuscated code. But the important thing is that means that you do need to tweak your web server so that you turn on compression. And you can figure this out just by opening up, actually, some of the new tools in Safari. You can look at all of your resources very easily, and you can just look at the headers and see if they've been gzipped. It's really easy to do. Along those lines, pay attention to caching. Sprout Core's build system actually makes sure that it generates unique URLs for every resource that it needs to include, including all of your images, all of your JavaScripts, all of your CSS. So what you should do with your web, except for the index HTML, because the user types that into the web browser, so we can't control that. So for all of your non-HTML resources, set up your web server so that it basically sends an expires header that's over a year in the future and sends a basically cache no revalidate header. And if you do that, you get this really cool feature, which is when someone first visits your website, they download your resources.
From there on out, the web browser not only doesn't need to re-download your resources, it won't even ask you for them. So you see no traffic coming off of loading those static resources anymore. If you're using a content distribution network, that's big savings, and it's going to make your app feel extremely fast. You're actually basically one step away from just having your app completely running on saved and installed on somebody's local computer that way just by using caching headers without having any of the local storage or offline mode that comes in Safari, which lets you go a little bit further. you can do it in today's web browsers just by using caching properly. Separate your dynamic and static content. You get all of these huge performance gains by actually letting your web application be a static website that loads and then talk to your back-end servers using JSON or something, XML or whatever you need to use. And then leverage the performance tools in Safari. And I already mentioned this earlier, but if you didn't get to the debugging sessions and performance sessions on Safari at the conference this year, make sure you check them out later. There's really cool stuff in WebKit. It's honestly, we talked to Safari team earlier this year, and I told them I'd really love to be able to do everything in Safari by now, and we are. I mean, I'm doing all my debugging, everything there, because they've just got outstanding tools. Highly recommend that you get to know those. So that's our presentation for SproutCore and building native applications on the web. If you want to get more information, get in touch with us. you can talk to Vicki Murley, who's our Safari Web Technologies evangelist. She's around here somewhere.
Documentation is on sproutcore.com documentation. You can install it using sudo gem install sproutcore. You'll get everything you need. Here are a couple other sessions you might be interested in. All of these have happened already, so unless you have a time machine, wait till they come out on ADC iTunes, and you can watch them then. And by then, I'm sure you'll obviously remember this slide in great detail. So just make sure you check it out. It's really good. Just to conclude, kind of wrap this up, kind of review a few of the things we talked about. If you come away with nothing else today, Web Client Server is the way to create rich, native look and feel applications in the web without needing any plug-ins. And you can do it with almost all of the web browsers that are deployed today. It's really easy if you adopt the right kind of model. It's not only easy, but it's a lot of fun, because you can really create these rich applications that have been reserved for the last few years for Cocoa developers. We get in on the party now. If you don't want to do everything from scratch and you want to save yourself having to relearn all of the intricacies of how to do this properly on all of the different web browsers, believe me, you don't want that pain. uSproutCore can get you there a lot faster. It's fun, and it's open source, so you can contribute to it. It's hosted on Git, so you can clone it and just, you know, hack away at it, and there's a lot of people doing that already. And load your application as static content. Use lots of caching. You can practically get installed offline applications today with most of the web browsers that are deployed if you just make use of this kind of deployment model. So that's how you create a native look-and-feel application on the web. There are some available today. You'll be able to check out a few more from Apple in a few weeks, and I hope you guys create a bunch of them, too.