Gonzalo Cordero: Yahoo! Local Mobile Case Study

Gonzalo Cordero: Yahoo! Local Mobile Case Study


>>GONZALO CORDERO: Hello everyone, thanks
for coming in. My name is Gonzalo Cordero, and I’m here today to share with you some
of the things I’ve learned while I was working on the Yahoo! Local mobile app. The agenda
for the talk is going to be… I’m going to show you a quick demo of how the app looks
like, and then we’re going to go into the moving pieces of the app and just try to dissect
it and explain what’s going on behind the scenes. Let me just show you a demo really quick of
what the app looks like and what it does. OK, let me move this out of the way. Cool.
OK, awesome. All right, so this is the app. Basically what this does is it shows you things
are going around your area, so in this case news, things to do, deals, events. It just
lets you browse around them, navigate around. While I demo the app, I want you to start
thinking in your head about which parts do you think are driven by web technologies,
and which ones do you think might be native? Then we’ll go after and discuss those. The first thing you might notice is this little
widget here, weather widget here. We can just navigate around, see things around Sunnyvale.
Let’s just get here to this little widget up here, on this site some of the movies are
playing, or were playing, in the movie theatre. We can just do this and nicely navigate through
all them. We can also do things like go into a detailed view of one of the movies. We get
presented with this view where we can just go around with a flicking behavior like that,
back and forth, and that will be changing the details of the page. We can also refresh
the data if we want to, doing something like that, pull down to refresh. I’m sure you’ve
seen it before. But yeah, basically that’s the app. Yeah.
What I want to do is just show you guys some of the things that are going on behind all
that, so let me go back to my presentation really quick. One of the first decisions that we needed
to face when we were designing this app was trying to decide which parts we wanted to
be native, and which parts we wanted to be web, right? Again, this isn’t like an exact
science, and each case might be different depending on what you’re trying to build,
but we kind of came to the conclusion that we wanted to use native for anything that
needed to tap into the hardware’s API, so anything that needed to access the device
we needed to use native for that. Obviously we also wanted to use native just so we could
put it on the app store, so yeah, that’s a big one I guess. That’s it, really. That’s
what we will use native for. There’s a few gotchas that I’m going to be
covering later on, but overall, that kind of still applies to when you’re trying to
think about designing your mobile web application or your hybrid application, this is when you
might want to be using native. Then web for everything else. Why? Because
you already know how to do it, and not only that, you’re probably already good at that,
too. You’re web developers and you live and breathe those technologies, so it should be
easier for you to be able to create a really good application just using HTML5, CSS, and
JavaScript, YUI. You can also, again, just write it once, use
it everywhere. So Android, iOS, Windows phone — anywhere. This is a big one, too, that
PMs love: being able to update your code and push updates whenever you want to without
having to submit an update to the app store and wait for the approval process and whatnot. It became clear to us that it seems like what
we wanted to create was something that combined both of them to create this hybrid application.
Again, you know, native, yes we used it, and we ended up using it more than we wanted to.
Why? Well, maybe it was the beginner’s price of not knowing, really, what we could do and
what we could achieve with web technologies. Some of these web technologies and some of
the features that we wanted to use weren’t reliable. Some of them were actually not there. What we used native for is anything that has
to do with geolocation, anything that means navigating through the app — so all those
navigation bars that you saw on the top and the bottom of the app, those are native — and
native storage. Now, you might be thinking why… We’ll go onto the web first, but we
used the web for everything else, so all the content, and all interactions. Do you remember that pulldown, to refresh
you remember I showed you that widget? That’s done using web, YUI. That’s a little Carousel
over there, just a ScrollView widget, and then the cover flow detail page that we saw;
that’s just using that flick event from YUI and CSS3. So this app is using Objective-C,
HTML5, CSS3, and the last piece was actually the easiest part to figure out and to make
a decision on, which is YUI. I want to take a little break here, a little
pause, just to make a little remark on YUI’s approach to mobile. I think it’s really remarkable
how YUI’s not diverging or branching off into two separate parts, creating one path for
mobile and one path for whatever we had before. Instead, we’re just creating one single library
that covers everything, because really, there’s no such thing as mobile web, there’s just
the web, there’s nothing… There’s no TV web, there’s no phone web, mobile web, just
the web. You shouldn’t be writing your code depending on where you’re trying to deploy
to; your code should just be working across all your devices. Just kind of like an analogy, when you’re
thinking about… When you were doing things like subscribing to an event using YUI or
any other library, you didn’t have to worry about which browser you were trying to deploy
to because you knew your library was going to just take care of all of that for you?
Well, the same way applies here: if you’re subscribing to a flick event, for example,
you don’t need to worry about, you know, where that code is going to run into. You know that
if you have a flick event that you’re going to be able to just do this with your finger
if you’re on a phone, or with your mouse if you’re on a PC. So that’s kind of like the
take away approach from YUI with all these new devices that we’re seeing. I just wanted to really make that remark.
And again, we’re using it, and this is some of the components that we use in the application.
We use Loader to load all the assets and JavaScript files and data, we use Events for anything
that has to do with interactions, and we use Substitute to do our templating, just a string
based replacement. Now, if I had to do this today, if I had to redo this application today,
I would have used transitions and the App Framework, but unfortunately the App Framework
wasn’t ready at the time we were working on this. That’s one of the biggest reasons why
we needed to create the full application using native components. With that out of the way, let’s go into actually
dissecting the app and seeing how it is. The first thing we need to do is delivering the
app. This is done through the app store, like I mentioned before. We put this on the app
store and that’s how people can start downloading it. Next question that came into our minds was
OK, what do we put in there? We ended up putting all the basic files, all the core files, including
YUI, and also everything that we knew wasn’t going to change frequently, so images, CSS
assets, things that we knew were going to persist for a while. Then the rest of the
pieces, we’ll just be loading them on demand as we need them. Obviously we use the Loader
for this. For those of you who don’t know what the Loader
does, the Loader will bring you what you need depending on what you’re trying to deploy
to. It will know all the dependencies, too, for you, so you don’t need to worry about
any of that. It will bring them in just when you need them, just when you asked for them,
which is pretty cool and pretty powerful, especially when you’re thinking about mobile
devices and you’re worried about space and HTTP requests and you don’t want to be overload
your app and bring in too much stuff that you might not need. Just bring it in when
you need it. Then you can use the Loader manually or automatically.
We ended up using it manually because we knew that our application was only needed to run
on the iPhone, but if you’re running something that needs to run everywhere — desktops,
mobile, TVs, everywhere — you can just specify the generic name of the package. Let’s say
I need Node. You can say just give me Node, and then the Loader will figure out which
device you’re trying to deploy to, and then it will just give you the specific that you
need for that device. That’s pretty cool, right? I mean that’s pretty powerful, not
having to worry about all the dependencies and where you’re trying to deploy to. You
just write it once and you’re good to go. Pretty cool stuff. Then once you have all of this, downloaded
all the different pieces, you definitely want to cache it, because when you’re thinking
about performance, especially on mobile devices, caching is one of the biggest ones so you
can reduce HTTP requests. And again, we’re using native for anything, like I mentioned
before, that has to do with storing, and then we’ll go into detail on that. You might be thinking or wondering: why don’t
you use HTML5 Manifest for caching all your data? We could, but at the time we saw some
inconsistencies. The first one that we saw was if we were to turn off the phone and then
turn it back on, all of our data would be gone. So that was kind of like a big issue
right there. I haven’t tried this in iOS 5 — that was at the time of iOS 4, so that
might have been fixed — but that’s one of the big ones. The other one was actually when
we wanted to flush the cache, it wasn’t that easy, and we had to go through many interactions
until we are actually able to flush it. That’s one of the reasons why we actually just ended
up using native storage. The other side of this is caching the data.
In this view, for example, we are on the old iOS view that you saw earlier, we might want
to load another similar view over there which is things to do, and the only difference between
the two is just the data, but the layout and everything is just the same. In this case,
all we’re doing is in memory, we’re keeping this template object and bringing JSON data
and then using Substitute to just parse it and just create the new view. Just a note on this: if you’re doing very
simple templating and parsing, I think it’s OK to do this, but if your templating is complex,
you probably want to do it on the server and then just bring everything constructed, even
the markup. Just a side note. The next one we’re going to go and talk about
is navigating. How do we move around the app, how do we do things like this, how do we go
from one point onto the other? Again, all the navigation is done using native. The reason
was some of the things that we wanted to use weren’t there, and there were a couple of
things. First, position: fixed wasn’t working on iOS 4. That little thing up there needed
to stay always on top, and that wasn’t working. That’s one. Then the other one was to create
something like this, being able to create a navigation control system where you could
remember where it was, and the previous and next and whatnot, well the App Framework wasn’t
there, so because of business pressures we didn’t have the time to roll around so we
decided just to go with native. However, this didn’t come cheap. Let me explain
to you what happens. This is the detailed view right here. Now, we want to be able to
click next and previous and go to the next view and to the previous view. Because all
the content is coming from the web, there is a real disconnect between the native part,
the native layer, and the web layer. We needed to load the whole thing first and also bring
in information about the next and previous document, just so we can pass it to the native
so the native layer will know what to do when someone clicks previous and next. Load the
view, block everything so the user wouldn’t really interact with anything and mess the
page, enable that one once it was loaded, and then send the article back and forth. As you can see, there are major drawbacks
with this. First we have more data than we needed. Now not only did we need to load the
whole thing, the whole view, but now we need to load information from the previous and
next argument. We also ran into different race conditions, like when the native view
needed to tell the web view it was ready and so on, so we needed to block everything until
both were the same page. Again, this also ended up in several bridge calls, which comes
with a price. We’ll talk later about the bridge and what that means. Again, if I had to do it again today, this
solution would have been much better, much easier and cleaner, and probably faster. Instead
of having all that nonsense I could have just had the App Framework, had a route that would
just load all these guys, and this guy would have had all the information needed in one
place. Same with transitions. I could have just done something like this. That much code
could have given me something like this, going from one place into another. Just JavaScript,
that easy. YUI. So again, doing all the navigation and all
the transitions with web means having one technology stack, being able to deploy everywhere,
and not having to worry about yet one more thing that you need to create for Android
or Windows or wherever you’re trying to deploy to. All right, the next part is gestures. Now
we have the application loaded, and now we know how to move around. Now we want to be
able to do things like this, like I showed earlier, being able to go with my finger or
with my mouse and just go and navigate away. How do we do it? Just that much code gives
you that effect that you saw earlier. Subscribing to a flick event, that easy. All you need
to do, really, is just get your container, subscribe to a flick event, pass in some options
— in this case the minimum distance I wanted to travel to the flick event to actually come
in place, the velocity, and the X axis. Once I had the event, do something, go to the next
movie or something like that. Now, again, I want to stress this point because
this is very important: that flick event would have worked the same on a PC. This is not
just for a phone. Now if I was to load my app on a browser, on a PC browser, I could
have done just this with my mouse and it would have worked just the same. You see the value
behind using YUI when you’re thinking about deploying your application everywhere. Now let’s say you also wanted to have a little
more control over what’s happening behind the scenes of that flick event. In that case
you can just use these low level events that we’re providing for you to actually have fine-tuned
control over what’s going on behind the scenes. Just a quick example: let’s say I wanted to
detect which direction the flick is happening, left or right, so I can populate the next
movie or the previous movie. In this case, all I need to do is subscribe to when the
movie lists are happening, detect it, grab it, and then once the gesture is done, then
detect the end point and then that way I can know where my flicking is going, to the right
or to the left. All of this is using all of the once and delegate goodness, and all that
sugar syntax. It’s really easy. We’re also using ScrollView. Like I showed
earlier, that little Carousel over there is using YUI ScrollView. It’s really fast, even
on low power devices, like the iPhone 3G. We loaded it with a bunch of movies and it
was just like no problem. All you needed to do… All it took to get that going was just
passing in some markup, in this case a list of elements with images, and then this much
JavaScript. I’m just specifying the srcNode, my flick event, the deceleration, the bouncing,
and the width of my cursor. And that’s all, that’s all it takes to get something in that
going. All right, so next up: offline and saving
mode. We’re talking now about offline, we’re talking about two different cases. First,
the one that we wanted to be able to load, or use, when the phone… We launched the
app and there’s no connectivity, and we still want to see something on the screen. So again,
for this one we’re just putting all the data that we need on native storage, and then just
Y Substitute to create and generate the view. For this one I think we could have gotten
away with just using local storage, HTML5 local storage, but we didn’t. But you know,
you probably could, and that’s probably reliable. That’s one part of the offline mode. The other bit is we wanted to be able to save
some items to consume later. Let’s say you’re seeing this movie information that you’re
interested in and you wanted to stop, take a look later, and you might not have connectivity,
you might be in airplane mode or something. We give you this save button that’s kind of
like the relist feature. At that point we will grab all the content and save it. We
needed to cache all the core files, which hopefully we already did have cached from
previously loading our view. All the content, obviously; by that I mean all the HTML and
CSS, JavaScript, and media, so videos. We wanted to be able to save trailers, movie
trailers, pictures, and things like that. Because we needed to do that, and they were
big files — again, native storage. So kind of like the conclusions for when you’re
thinking about saving and offline caching is if you need something that’s very big,
use native. Otherwise, if you’re just caching or saving data, you probably can get away
with just using local storage and just using templating to generate your views. All right, so let’s talk about the bridge.
The bridge is just a way to communicate, to enable bidirectional communication between
the web and the native layer. Some examples where we used the bridge, going from native
to web, would be we had this view where were putting articles and we needed to be able
to bump or decrease the font size. Because, again, the controls were done natively, we
needed to create this communication between native and web. Someone will type in there
and it will make the things bigger. Send an event to the web view, and the web view will
apply a new class name, and that’s all it took. How do we do that? Well, Objective-C native
gives you the ability to parse and to execute JavaScript via eval. What this means is that
you need to provide access to some global space for JavaScript… I mean, for Objective-C
to call into. We just did that, putting some function on the Y.Env space that the native
could call into. Once we grabbed it, we’ll have a little switch statement depending on
the action, and it will call with Y.applyTo() on the right YUI module. It’s not too complicated.
That’s how you do from native to web. From web to native, there are two ways you
can do it: via XHR, or window.location. All you need to do is just navigate to a protocol
that both the native layer and the web layer agree upon. Using window.location, all you
have to do is something like this. You specify a protocol, whatever that is, and you pass
in a URL. The URL can be anything you want; in this case I’m just doing something like
my action parameter one equals to foo, or blah blah blah. Then on the native side of
things you just need to be watching for the protocol, and if it matches then you intercept
it, you prevent default if you want to call that and translate it to web. Then parse the
request and do something. Otherwise, just keep on navigating. That’s kind of a pseudo-call,
is how this works. You could also use XHR if you want to. However,
if you’re loading your content from a different domain and that content is trying to make
a bridge call, you will run into cross domain policies and restrictions. It works nice when
all your content is coming from the device, when you’re accessing just the file system.
This is kind of cool because you can also take advantage of the whole success handler
and send data back, so this is kind of a little bit of feedback between the native and the
web, so it’s even more reliable. With that, that’s kind of like all the moving
pieces, general moving pieces of the app. What I want to cover now is I want to share
with you some of the best general practices that we learned while working on this. First,
everything you’ve learned through all these years, all the YUIConfs that you attended,
all the YUI Theaters you watched, all those tech talks, everything, it still applies.
And it applies more than ever, because when you’re thinking about these devices, you’re
thinking yes, WebKit, now I can use WebKit and all of HTML5 and I don’t need to worry
about all this stuff I learned for IE6 and how flawed it was, and blah blah blah. But
the thing you don’t realize is that the Webkit on your phone is not the WebKit on your computer.
The WebKit on your phone is more like your computer like five years ago. So keep your JavaScript small, because now
you’re not only worrying about performance and memory consumption and all that, now you
need to worry about battery, which is something new to all of us web developers. Your JavaScript,
keep it small. Don’t touch the DOM, that still applies. Same principle. Keep it small. Again,
every byte counts double in the mobile space, just because we’re so constrained with the
memory and HTTP requests and things, so watch out for your JavaScript. Reduce the HTTP requests. This is a big one.
How do you do it? Pre-pack as much as you can. Put it on the app, deliver it, get rid
of all the small images, backgrounds, that you might have through your CSS. There is
a great tool that Nicholas Zakas wrote that will go ahead and parse all your CSS, download
all the images, and then convert them for you into data URI and then put them back into
your CSS. At the end of the presentation I have a slide with all the resources, so once
I put it up you can download it and take a look if you want to. Then again, just use
cached templates for loading stuff that’s probably similar. Perceived performance. This is a big one.
Just make sure you’re always in touch with your user. Give the user constant feedback.
Because you don’t want your user to tap somewhere and then nothing happens, and he thinks something
is broken and slow, and he keeps on tapping and tapping resulting in multiple HTTP requests,
or who knows. Make sure you’re in constant touch with the user. Shrink your images. If you’re consuming content
from your desktop, make sure you shrink it down, because you don’t really need those
big images for your phone. So again, HTTP requests: very expensive. And last, take advantage of all the shiny
stuff, right? Use CSS3 as much as you can, and don’t use images. Take shadows, block
shadows, but again, watch out for those because those are also memory hungry, so if your design
has a lot of shadows of any kind, re-think about it. You probably don’t need all of them
because they’re very memory hungry. Hardware acceleration: use it, but don’t abuse it,
because every time you do something like that it creates an image and that image takes a
space in memory. Again, watch out for those. And lastly, just use all the HTML5 goodness,
all the semantic new stuff. Almost there, but I do have one more thing
I waned to kind of ask all of you, which is: if you have something that you’ve been creating
and you’ve been working on, please consider contributing to the Gallery. Some of the things
that you’ve seen today, some of the modules you’ve seen today, like the pulldown to refresh
and the Carousel, we put it up on the Gallery for everyone to use. If you have something
cool going on, put it into the Gallery because that’s the only thing we’re going to make
this great library even better. Final thoughts. YUI is very well suited to
create both hybrid and web applications, and there’s nothing stopping you from using and
creating web applications using mobile web applications using YUI. This is the resources. That’s all I have.
Thank you. [applause]

Author:

2 thoughts on “Gonzalo Cordero: Yahoo! Local Mobile Case Study”

Leave a Reply

Your email address will not be published. Required fields are marked *