Skip to content

Instantly share code, notes, and snippets.

@voodootikigod
Created June 22, 2015 14:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save voodootikigod/c546de804bcb7f8240d7 to your computer and use it in GitHub Desktop.
Save voodootikigod/c546de804bcb7f8240d7 to your computer and use it in GitHub Desktop.
JSConf US 2015 Track A Transcript for Kate Hudson: Beyond Responsive: Building a mobile web you're f*ing proud of

Hi. Everybody hear me okay? Yes? Awesome. So I'm a web developer at Mozilla, I'm the lead engineer on the Webmaker for Android project, and I want to start off on a high note here. The web is broken. And I don't mean the Wi-Fi. Although the Wi-Fi is totally broken right now. So I'm not going to demo some of the stuff I was going to show you. But that's okay. It's not actually broken for most of you JavaScript developers, right? On Firefox and Chrome and Edge, for you, the web is probably still pretty awesome. But for the rest of the world coming online right now, and that's like 2 billion people over the next few years, it really kind of sucks. And that's just because for more and more people, the first and only experience they're ever going to have of the web is mobile. And the mobile web is not good enough. So let's talk about why the mobile web is not good enough. You probably know most of this already. The one that you are probably feeling a lot right now is UI perf. Particularly when you're doing things like gestures and lots of layout panes -- not great. Not as good as we'd like. But there's lots of other things that are broken. The auth model that's based on email doesn't make any sense for new users of the web who don't even have emails. The experience when you go offline or you're on a 3G or less connection is really pretty terrible for most of the web. And of course, all of the access to the OS level device integrations, like push notifications, and camera. And on the one hand, that's okay. The web was built for a completely different desktop-based paradigm, right? And it's going to take some time for browsers to work on solutions. Right? That's fine. But on the other hand, it's kind of not okay, because not only does the web kind of suck at all these things right now, native platforms are actually really good at them. And there's some technical reasons why performance and other things are easy to get right on native platforms. But the thing with native is it was built with these problems at the center of its business model, and the web was not. So I was actually kind of wondering -- you know, is this still something that people care about? Are we still talking about this? And it turns out it is. Just yesterday, actually, one of the leading authorities on browser quirks and compatibility since the '90s, I think -- he wrote an article on his blog, and it was called web versus native. Let's concede defeat. I want to read this out, because it's important. I feel like it's time to revisit the web versus native debate and concede defeat, that the web should not and cannot compete with native when it comes to complex app-like structures. His argument essentially is that because of the fundamental architectural limitations of how the web was built, we're just going to have to give up on building these rich client app-like experiences and go back to the true strengths of the web, which is URLs, universal accessibility, et cetera. And you know what? He has a point. You know, overlooking the fact that there's a few things like offline that still affects the overall interoperability of the web, this is a totally reasonable, rational argument, when you look at the current state of affairs. And it might actually even be a popular one. Honestly, if what you really want to do right now today is to build the fastest, coolest, most awesome UI, with 3D and games and whatever, I would have to tell you -- you know what? You should consider building for Android or iOS. But if what we're saying -- that this is the way to fix the mobile web, it's to give up and abandon app-like experiences for something that, you know, works better with our original model of the web, I couldn't disagree more.

But to do that, first, I want to take a look back at the year 2004. How many of you were doing web development back in 2004? Wow. That's a lot of you. This is awesome. So you're totally going to remember some of the stuff I'm going to talk about here. So... Yeah, I was a big fan, actually, of both Britney Spears and Orlando Bloom. According to Google's zeitgeist of the year, they were the two most popular people. The top two tech topics, according to Google analytics, number one was wallpaper. Number two was Kazaa. Yeah. If we were doing JSConf in 2004, that's what we would be talking about. Pretty awesome. So also -- PHP5 was released that year, Ruby on Rails was at 0.5.0, and Google had been around for about six years already. So that's cool. So something else happened in 2004. It was the year -- actually, it was the year that Facebook was released as well. Although I don't actually remember that. But it was actually the year that Google first released Gmail. And at first, because it was released in April and Google had this reputation for being notorious for April fool's jokes, people thought it was maybe a joke. Does anybody remember when Gmail came out? Were you signed up for Gmail? Yeah. I don't remember it being as cool as people said it was. But it was... I guess was pretty cool. It was a real thing, and it was cool for two reasons. Okay? One was that it offered a gig of storage. Where all the other online competitors like Hotmail and Yahoo offered way less than that, and the second thing was that Gmail had this super neat interface that could actually live update when you received a new email, without requiring a page refresh. That was super awesome, right? And in 2004, the idea of re-rendering the DOM with new data, after the page had loaded, so like... AJAX, was not at all common on the web, nor was it even expected. All the other web email clients were terrible and clunky and required lots of page refreshes, but that was just the way things were. If you wanted an app-like experience, you were expected to use a Windows email client. Right? Pretty reasonable. So when the lead developer of Gmail told his co-workers he was going to write the entire app totally in the browser and almost entirely in JavaScript, they were like... What? Really? You know, in fact, almost everybody he talked to, even internally at Google, especially people who considered themselves to be experts at JavaScript and the web, thought his idea was totally naive, it was never going to work, because people had tried to write complex things in JavaScript before, and they knew the web was just not made to do that kind of stuff. And this was a really common opinion at the time. JavaScript was at best a thing that... You know, could decorate your pages or enhance them a little bit, and at worst, it was a security flaw, it was non-standards compliant, it was disruptive and pretty terrible, right? So I want to show you some things that people were actually writing. I was digging back into the Wayback Machine and some old blogs circa 2004. This was from the anti-JavaScript FAQ. While I am personally opposed to all JavaScript, I understand it can do some things that you can't do with normal html. But just remember -- if Amazon can do without JavaScript, so can you. So this was from a post titled JavaScript is evil. A lot of designers think it's their god-given right to annoy the hell out of visitors with bulky JavaScript effects, so turning off JavaScript is almost a requirement when visiting some websites. It was true at the time. This is from stupid JavaScript security tricks. A little bit older, but still relevant. Blindly accepting a high level of security risk on the web by enabling JavaScript is as shaky as a ride on the Canadian space shuttle made of birch bark and gum. I'm Canadian, so this really resonated with me. Woo, represent. So this is what people were saying. JavaScript was not a thing. But despite the fact that it took years for Gmail to... Whoops. Uh-oh. My computer died. I'm going to have to plug in. Okay. I don't need internet. But... Sorry about that. So... Computers fail sometimes. Not only is the mobile web broken. Batteries are broken too. Yeah. Oh, thanks. You're the best. See? Community. This is what makes JavaScript better. All right. Let's boot up. Sorry. It was the Gmail curse, honestly.

(Never Going to Give You Up playing)

Oh, gosh. All right, we're booting, we're booting. I'm really sorry. Phones were super different?

Phones were super different in the '80s than they are today.

Yeah, they were.

In the '80s, I had Jenny's number, and now I have 8675309 apps on my phone.

It's true. It was really different back in the 2000s too -- people assumed email could only be done native. But we're about to find out why... Yeah, it's just going to take a minute. Okay. Should have plugged in. Yeah, it's true. Oh, we're good, we're good, we're good. Sorry, sorry. All right. We're back.

Let's hear it for the hibernate feature on computers, everybody. As opposed to rebooting from scratch.

(Never Going to Give You Up playing)

We're back. No, we're not back. Now... Which one was the right one? Probably this one. Let's find out. Yes! Okay! So... We're back. We're back in the immersive interactive web. Awesome. Still in 2004. So despite all of this weird stuff, and the fact that JavaScript was terrible, and it was a total hack, Gmail was a total hack, it was living proof that you could write something in JavaScript that people actually loved. And that's awesome. And, you know, it wasn't long after this that developers started getting excited about the XML-HTTP thing and using it all over the place, and before we knew it, great rich client experiences became something that was essential to the web, as the promise of interoperability itself. Fast-forward to 2006, and all of a sudden XML-HTTP thing has now been standardized by the W3C, and JavaScript is moving towards the process of standardization and universal acceptance. Hurray! Clap for JavaScript! So the point is this: you're not here at this conference about to learn about knitting and making music and driving robots because someone intended or designed to make JavaScript or the web to do these things. You're not here because of the standards body. You're not even here because of a browser. Well, you're kind of here because of a browser. But not entirely because of a browser. You're here because someone wanted to do something cool and found a super hacky but somewhat compelling way to make it happen. So my proposal to fix the mobile web is this: stop relying on browsers to reimplement the DOM or land device APIs or do whatever it is you want. Stop thinking about what the web is or what the web was. Maybe this is totally naive, but I don't think that rich app-like experiences are something we're going to be able to pass over, no matter how compelling and awesome the URL is. And if you want to talk to me about URLs, I will talk you to about URLs. If you want to be here, talking about JavaScript, in five years, it's time to hack. So in order to demonstrate some of the ways you might do this today, I would like to use a model I've devised called the three levels of hack. Where we start in a place that most people would kind of agree is not that weird, and then end up with something that's really weird. So start small. First level of hack. Test new features before their time. That's a great way to push the platform a little bit. To use new browser language features, right? That haven't made it into production. So one way to do that is to turn on stuff that's there and use it. Easy, right? One thing I'm personally really excited about is the service worker -- which is going to help out with offline in a huge way. And I'm not going to talk about it in detail, but if you've ever used AppCache or are thinking about taking your app online, you should definitely check it out. There's already an implementation. Chrome, you can check it out today, and I think the Firefox implementation is coming out in the summer sometime. So that's super cool. You can also polyfill the features that you want to make them work for features today. One of the things we do on my team is transpile ES6 using Babel. And Sebastian is speaking about that later this afternoon. So I highly recommend you attend that session. And doing this kind of stuff is not controversial. But I'm mentioning it because if you're not doing it, you should. And the other thing you should do is -- if you find bugs, or you have opinions about how things should be changed, you know, the implementation teams that are building them really want to hear from you. The Gecko team, for example, working really hard on service workers right now, is really interested on getting feedback on the service worker and how you want to use it. So if you're interested in joining that conversation, just talk to me after and I can hook you up with the right people. Okay. So let's do the second level of hack.

Building new abstractions. So beyond things that are being implemented -- cool stuff really comes out of people thinking in completely different ways with the tools that are there. So, you know, one area we're seeing a lot of innovation -- I'm sure all of you are aware, probably using this stuff -- is DOM abstractions, like Reacts, virtual DOM, famous engines DOM and web GL abstraction, flip board did a cool thing with react and canvas. For the most part, they don't replace the DOM. They augment and reoptimize particular areas of it by building an abstraction, and that's pretty cool. It's a total hack. Let's be honest. But it's awesome. Another thing you can do with abstractions is build things that already exist, but don't yet exist -- have a counterpart on the web. So going back to the offline use case, a pretty cool example I've seen in the last few months is some colleagues of mine have been working on something called Filer, which is basically a POSIX compliant file system interface in the browser. It doesn't actually use a file system. It just abstracts one on top of index DB or web SQL or even in memory. So that means that any modern browser who has access to those things can actually do file operations and store them offline, which is amazing. There's a group of super smart people working on a code editor that takes advantage of Filer at Seneca College in Toronto, so you should check that out if you're interested in Filer. It's super cool.

So... Okay. We talked about some fairly... You know, things that are exciting. But not exactly controversial. Because we're still building on top of existing APIs, and mostly doing things in a web-like way. But what if we could go actually further than that? You know, if the browser is the thing that holds you back, why not just hack on that? Cool, right? And in this case, I'm not talking about, like, submitting a patch to Firefox for Android, although if you would like to do that, there's a link. You know, totally awesome. You totally can and should. What I'm talking about is basically hacking together your own user agent inside of a native environment. And this is also known as hybrid app development. Right? And maybe you haven't heard hybrid app development described quite like that. Hacking together your own user agent. That's essentially what it is. And there's some frameworks out there that can take care of the dirtiest part of that hack. If you want to try them out, I would highly recommend Cordova, which is a really brilliant project that feels the closest to actually still developing with the web, but getting APIs from the native device. But I do actually think it's valuable to do yourself. You know, are you going to implement a better browser for all mobile users? You know, are you smarter than the people who work on Firefox and Chrome, and Windows? Absolutely not. You're not. I'm sorry. Maybe you are. I don't know. Come work for us if you are. But you're probably not. But... You know, personally, for what I'm working on... No, seriously. Come talk to me. For what I'm working on, I found that building a custom hybrid architecture, while it's not the solution for all of the web's problems, it allowed me to experiment with solving the exact problems that we were having with the mobile web, and understanding that connection much better than I would, you know, using something like Cordova, or just building within the browser. So to put this into perspective, I'm going to talk a little bit about what my team at Mozilla is working on. We're interested in what web authoring tools might look like, primarily for new users of the web in Bangladesh, Brazil, India, and Kenya, using only a mobile phone. So that's, like, what our problem is.

And the first iteration we experimented with was a client side single page app. We didn't target iOS, because it's not a huge part of our market. But we had specific issues that were major blockers. Obviously we needed to make something work really, really well offline, and in 3G or less. That was a huge requirement for us. We tried using AppCache, but it wasn't doing what we needed it to do. We were seeing a lot of issues with memory leaks popping up in client side memory architectures, particularly when building or destroying new views. Especially when people are idling the apps on their phone for three or four hours. That was a huge issue for us. Another big issue was UI perf. It's an editing interface when you touch. And 50% of our user were still using Android phones before 4.4. Anybody develop for the stock Android browser? Nobody? Oh my goodness. You think IE is bad. You should try developing for the Android soft browser. It does not autoupdate. It's pretty horrible. So these were problems.

Let's figure out how we fix some of these things in a custom Android environment. So... Actually, any Android developers here? No? Oh, we've got one. This is good. This is good. All right. This is going to be interesting to you. So I was going to skip past this part. If you guys all do Android. But... All right. So the basic architecture -- how do we build this custom hybrid app? And by the way, this is really similar to how Cordova works or any other hybrid architecture. I want you to understand how you do it yourself. So the first thing we do is we start with an Android activity, which is like a basic view in Android. And that may or may not contain some UI, like a back button or a header. Or it might just be like a frame to hold the web view. All right? So how do we do that? We write some Java. We create an activity. We create the layout in XML. Then we add it to the manifest, where we can specify things like the name and the parent view, the view hierarchy, stuff like that. It's kind of weird, but not so weird. Inside that, we instantiate a web runtime. That can be Chromium or even Gecko. There's a project to do that, but it's not ready yet. That's super cool. And Android makes it easy to do. In 4.4 plus or web kit -- you just implement the class instantiate. Super easies, right? Like us, you probably want to support the most modern version of browsers. Instead of using the built in Webkit, you can use this, which is crosswalk. Lets you embed the latest version of Android as far back as 4.0. And it exposes the same JavaScript Java bindings -- it's great. Crosswalk project.org. So the last thing we're going to need in this architecture is a communication layer that binds our JavaScript and our Android code together. Some of that is provided by the web view class or the crosswalk class, so you can load external URLs, you can load packaged assets inside your app. And if you're wondering -- yes, even if you're using the file protocol, you can do XHR, because this is your own user agent, and you can do what you want.

All right. But the real magic that happens, though, is you can expose a custom Java interface into your JavaScript by attaching it to the window object, and that kind of lets you do whatever you want. So what does that look like? We've got -- we add JavaScript interface to our web view, we basically attach a class to it, and we can add some methods on that class. And those methods that are declared actually show up on window.Android, or whatever -- we can call it whatever we want. I called it Android. We can just call those Java functions. Of course, you're fairly limited in what kind of data structures you can pass through. You're going to want to use primitives like strings and stuff. You can't pass full objects or functions around. Sorry. But... It's still pretty powerful.

And that's basically it. So... Yeah. That's how it works. If you remember from our example, one of the major issues we had was that the client side routing caused a lot of unexpected memory leaks. Long lived processes were kind of not so great in our client side app. So what we did -- and this is something you couldn't do in Cordova, but we could, because we were hacking something together -- in order to fix the issue we had, we actually moved the routing into Android, so we could take advantage of the more sophisticated memory management and life cycle events, and we instantiated each page of the app as an isolated view with its own activity. That's really similar to server side routing, and it actually has the same benefits, like encapsulation of each page, but in Android, we also get the added benefit of super smooth transitions, layout hierarchies, we can get the back button to do what we want, so we get the best of both worlds. Pretty cool. What did we do about shared state? This is where the JS Java bindings come in. Because we're using React to render the web UI, it's pretty trivial to send parameters into React and take the state out of React and cache in Android. So what does passing rooted params look like? You stringify the router params, get an initial state function, and all of a sudden you have all the information from your router. That's pretty simple. And to cache state, we create a JavaScript interface called setState, that allows us to pass in a stringified JSON object, so it can be cached in the shared preferences in Android. And our React code, we just need to hook into it. So every time our component updates, we set the state in Android, so it's cached, and when the component mounts, we just pull it down and then restore the state. So super simple. But it solves a problem -- we can restore things in an offline context, we can get around using that Android-based routing, without having to sacrifice our User Experience. So what about device integration? This is something actually if you're going to do it, you should look at the Cordova code base. There's a lot of things that looked at device integration. Here we write some of the typical code you would write in an Android app for dispatching the camera intent, looking at whether you want a camera or gallery, we create a URI out of our image, or we could do something like upload it at that point in time. And then we actually post it in this super awesome hacky JavaScript window thing.

We actually post it to a method in JavaScript, we post the URI, and then all of a sudden we can use it in our JavaScript. So it seems totally terrible, but hey -- you get an understanding of how Android is receiving the camera intent. You get an understanding of what you can do in terms of compression. You get to be a lot closer to your device than you ever would be using some web API or just saying... Well, we can't support camera. So what else? There's lots of things you can do. You can bind to Android's offline network caching utilities. You know, if you want to do that -- before service workers are available. You can hook into some native gestures, so you could actually read gestures on the Android side and post them into JavaScript. If you want to do things like pinch zooms or swipes that are much better architected in the Android platform. And of course, you can do lots of device integration, like push notifications or whatever you want. And really, it's up to you. Because it's your browser. Well, it's your user agent.

So... The truth is I'm not really sure any of this is going to be actually successful. Or even that it's reasonable or possible to make fundamental changes to the mobile web in this way that works. But what I am certain of is if you don't try bold, native things -- naive things, and develop a better understanding of the platform you're building for, you know, if all you're doing is pushing up against the edges of the browser, things are not going to change. No one is going to fix the web but you, and your understanding of your real problems. So I want to end with something inspired by my dad. This is my dad. Because one, he was pretty much the coolest engineer I've ever met in my life. And two, because Friday would have been his 71st birthday. So happy birthday, dad. Thanks. So my dad was totally self-taught. He was an amateur radio hacker, and he also designed some really, really cool radical electronics equipment back in the '60s, '70s, and '80s. He worked with a lot of people who had engineering degrees, and one of the things he said all the time was -- for all their education and understanding of theory, a lot of people just didn't really get what good engineering was. Good engineering. Because to my dad, really good engineering was finding adequate solutions to problems that really matter to people. In a way that someone in the future, who's smarter and better than you can understand and improve on. And as long as you're okay with the fact that the web is always going to be this patchwork, open, weird, somewhat hacky, totally imperfect thing, as long as you're willing to think about it and build for the real world around you, and not for what the platform tells you to do, you're probably going to make something great. You know, for the 500 things that suck and are terrible, you're going to make something great. And if the talks we have lined up... You know, in the next few days, are any indication of what people think about that, I think we're going to be fine. So hack the good hack, my friends. Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment