Web Vs Native at State of the Browser 2

(via Steve Workman)

I was at State of the Browser 2 yesterday, an event comprising reps from the browsers. I’m happy to be part of this event as I think it’s valuable for the web as a whole for devrels to get together with developers in this way. The browsers do spend a lot of time talking to each other about specs etc in meetings and mailing lists, but at State of the Browser, they’re facing the developers. So straight up, thanks to the organisers for doing a great job running this great event again.

Thankyou for the sketchnotes UBelly 🙂

Slides for my keynote talk on Web vs Native are here. I’ll highlight the four challenges of the web which

In order of increasing threat, I mentioned:

  • UI Low threat. A lot of the capabilities are already in place and we can already do decent UIs if not “gorgeous”/”sexy” like Path or Paper.

  • Offline Medium threat. DHH wrote his famous You’re Not on a Plane argument in the desktop era. Mobile is way important these days, connectivity remains sketchy, and 3G is expensive for many. The pure offline scenario may matter less, at least for many people in developed nations, but latency matters a lot to everyone. HTML5 does have offline technologies, but browser support is extremely fragmented and there are many debates about what to use where.

  • Device Integration Medium threat. Web needs permissioned access to camera, contacts, etc. But my bigger concern is peripheral aspects like single sign-on, notifications, Android intents. These things, for the most part, are not possible in web apps. There are signs that’s changing as the speakers yesterday highlighted, e.g. Chrome’s adding Web Intents, IE’s adding native notifications like the OSX native notifications I mentioned. But it’s really early days, and I don’t see anyone talking about single sign-on for web apps, which is hugely concerning considering how personal in nature smartphones and native apps are.

  • Background Processing High threat. This doesn’t get much play, but is something I’ve been thinking about since writing this and listening to the related Jason Grigsby podcast. With modern smartphone apps, we see the long-anticipated trend of software that acts as intelligent agents. An app is not just something you open, interact with, and close. Through its smartphone vehicle, the app serves as an extra brain, extra set of eyes and ears, extra communication agent. With you at all times, proactively scanning the environment for anything useful. Sucking down content and syncing with servers. Notifying you when anything particular important happens. Web apps are shut out of this game. They are useful as long as the user is looking at them. Out of sight, out of mind. Or more generously, as long as they are still open in a tab, but they may have restricted functionality in mobile background tabs to preserve battery life. Chrome has done some work here with background apps, but it’s really early days and I don’t see anyone thinking about this problem in mobile space.

I also mentioned monetization and competing standards as additional threats, only reason I didn’t cover them in detail is time. I did mention a little of it in the recent bonus HNPod episode on HTML5 vs Native and we had a Twitter conversation about it yesterday.

Remy blogged all the morning talks and raised some questions about each.

Is the point: browsers don’t matter – the web does…?

The underlying assumption is that the web matters more than any individual browser.

Should the browser just be the webview?

No. Browsers add a lot of value beyond the web view. One of many examples is customisation via preferences and extensions.

“You’re not on a fucking plane” – but then do all devs know how to build apps like gmail where it’s insanely quick because they know how to work the mobile device?

Agree. It’s hard right now. And even harder if you wish to use the same core app for both online and offline (as well as desktop and mobile).

AppCache is not a replicatement (sic.) for localStorage – far from it.

Definitely not.

Is there a larger problem that the browser (and a pro) exposes data if the user wants to get to it. It makes SSO harder because of security, etc?

Yes, but just like camera access, geolocation, etc, you can handle it with permissions. If HTML5 doesn’t stay competitive with native on SSO, background apps, etc, it’s not going to be a modern platform for apps. There’s enough UI widgets already, it’s these peripheral aspects — those where security is an issue — where native is surging ahead. You can either do basic websites without app-iness or you can do apps which use the full range of possibilities available in a modern device and operating system.

Web vs. Native seems like two issues: browser and the web. Browsers being the limitation

Both as we’d want web standards too for whatever the browsers offer developers. But definitely down to the browsers and possibly the OSs when you consider SSO for example.

The panel I moderated. Devrels from four browsers and the forbidden fruit. (via james_smith88)

Rails Cache Sweeper Gotchas

As you’ll see here, Rails cache sweepers are a tricky subject. Here are some general things I’ve learned.

  • Sweepers are dual creatures. “Here’s the scoop: sweepers observe both your models and your controllers. They’re not half-this and half-that, they’re both_. You can define model callbacks (after_save, afterupdate, etc.), and you can also define before/after callbacks for any controller action (e.g. after_list_create).”

  • Notwithstanding the above, most references and despairing workarounds focus on their controller nature. Dandy for a web forms app, but in my case, cached content is being invalidated by daemon processes operating directly on models.

  • There’s no standard home for Sweepers. So much for convention-over-configuration :). So I opted for a new app/sweepers directory and added it in application.rb: config.autoload_paths += %W(#{config.root}/app/sweepers).

  • Now to the crux of the matter: The Sweeper still does nothing, even if it’s in the path. I don’t know why, but it’s a common problem! I had to explicitly add it as an observer: config.active_record.observers = :episode_sweeper. This is the model equivalent of people explicitly adding it to their controller with an after_update hook.

  • Now to the crux of the matter, redux: Okay, so now the sweeper is being called when models change (specifically, the models it declares it’s observing). Great. But it still doesn’t work — expire_fragment apparently doesn’t, because I’m still seeing the the old fragment appear in the web app. WAT? The answer turned out to be, don’t just call expire_fragment(). Instead, call ActionController::Base.new.expire_fragment(). It seems the fragment used when outputting a view is not the same as that expired by expire_fragment(). I’m only telling you what worked here, I can’t tell you why!

  • You can also expire cache in the Rails console for testing purposes, just call ActionController::Base.new.expire_fragment(). (I think you need to restart Rails (and the console) if you update the sweeper code, given that it’s set up as an arel observer in the config line above. But haven’t fully tested that.)

This is just a basic implementation for now. A better implementation is probably to use DHH’s key-based caching approach, which has the neat principle of generating a new key every time the fragment changes.

The New New Podcast

It’s been a while since I’ve podcasted on this site, having shifted my attention to live gigs in recent years. But I’m pleased to say I’ve begun podcasting again at AudioBoo.

Doing my best to keep this lightweight and sticking within the base 5 minute limit for now. And focusing on HTML5/web development. I’ve taken inspiration from the excellent Boagworld podcast for this short Audioboo-powered format.

It’s now 7.5 years since I began my original podcast, a few months after the technology was born and shortly after I set up ye olde podcast FAQ at http://podca.st. My podcast is actually the reason I set this here blog up. I’ve continued to be enthusiastic about the medium and it’s heartening that podcasts continue to thrive in 2012. So in addition to announcing the Audioboo, I’m pleased to say I’m working on a service to make life a little more pleasant for the fellow podcast listener. It sees the light of day Real Soon Now — please ping me at [email protected] if you’d like early access and can give some feedback.

Rough Notes from Johan Ronsse’s Design for Developers Slides

Clearing my desk and buried at the bottom of the pile was some notes I took a while ago while running through this slideshow. My notes are just capturing a few points to remind myself later and don’t do the slides a speck of justice. So check out the slideshow instead, which Johan went through after his talk and optimised for reading.

Design for developers
View more presentations from Johan Ronsse

Fonts and Layout

Avoid font-face for performance reasons. A good font is Verdana or Lucid Grande, fallback Lucida Sans Unicode.

Android: Droid Sans, WP7: Segoe UI

All text at least 14px Consider 16px default For Lucidea Grande or Verdana: 11-13px

Paras <= 60 characters wide

1.1 line-height for headings, 1.5 for paragraphs

Grid structure: think in units of 6.

Light and Shadow

1-3px drop shadow

0-3px distance

Inner shadow when button is depressed


Recommended: Hues app

Start with three colors

Blend foreground color with background color for text (ie don’t just use pure gray/black if there’s a colored background)

Dark gray with blueish tint looks good. Blue bottom is common (e.g. on GitHub)

Use at least as dark as #d5d5d5 on white background

Pay for good icons, e.g. Picons/Pictos/Fico

(This was just after I took the UX Bootcamp on Visual Design, and – look away now – I’ve also posted some moodboards from around then.)

Twitter Debates Happen When Blogs Lack Comments

2004 Rehash Alert, Meta Alert

Christian Heilmann takes people to task for conducting debates on Twitter. The irony about this is the post that triggered these debates concludes thus:

I don’t have comments on my blog but I’d love to hear from you if you feel the same way (or not). Tweet at me, discuss on HN/etc, or pick some other method and I’d be happy to chat about it, just not over a beer 🙂

The double-irony is that Christian’s blog also doesn’t have comments. (I thought it did before, maybe that’s temporary.)

Anyway, this is an age-old debate about blogs and comments, and I sure know the pain of maintaining comments in the face of endless blogspam (see below). So while I certainly wish more blogs would have comments, I’m sympathetic to those which don’t. All I’m saying is the conversation will happen more on other channels in the absence of blog comments. Some posts are notable enough to float to the top of HN, where there’s a built-in comments mechanism. But for the rest, Twitter is going to be the place.

(Incidentally, Josh Schachter’s TinyThread was quite a neat idea for offlining a conversation. Not ideal , e.g. everything’s designed around being able to tweet comments, but the basic concept had potential. Never took off though.)

Detecting Android Browser, But Not Chrome

“A browser’s user-agent string isn’t an identifier, it’s a reverse-chronological history of the web.” – Jeremy Keith

I have to perform evil browser-sniffing because Android Browser is … special. A little slow and using SoundManager, a little different.

Well, today I installed Ice Cream Sandwich (Android 4.0) on the Nexus today, much hat tips due to the Cyanogenmod wiki guide. So I can finally try out Chrome on Android, and it’s actually sweet. In fact, on first impressions, it has more in common with Chrome on Desktop than it has with the standard Android Browser. So I had to update the evil sniff code to exclude Chrome.

Both browsers present as “Android” and “Mobile”. Chrome additionally presents as “CrMo”. So my new CoffeeScript to detect Android Browser, but not Chrome, is this:

  1. isAndroid = ->
  2.   ua = navigator.userAgent.toLowerCase()
  3.   ua.indexOf("android") != -1
  4.     and ua.indexOf("mobile") != -1
  5.     and ua.indexOf("crmo")==-1

Update: And as Pornelski points out, there’s also Firefox, Opera, et al. How I end up grouping them is still up in the air, so consider this a work in progress.

Originally adapted from here.

Confirming User Wants to Leave the Page

So you have a user at your site and they wants to close your site or go elsewhere. In the past, the most likely way this would happen is clicking a link. But these days, almost all links are “target=_blank” popup links, and it’s become so standard that it’s almost rude not to. So that’s not a scenario to consider. The scenario is where the user has closed your tab, perhaps inadvertently as part of a mass “close all tabs” or “quit browser” operation. Or they’ve typed in a new URL.

Most websites should in all sanity just concede at this point. Let the user be in charge and just move on from your site.

Some websites do have a legitimate need to do some work though. In the simplest case, they may just want to upload analytics. In more complex cases, they may want to save unsaved work. You can generally do that silently with an onbeforeunload handler.

And a scarce few websites may have a legitimate reason to confirm the user’s action. I’d argue for a video or audio app like the one I’m building, that’s what the user wants. If they’re explicitly subjecting themselves to the audio stream coming out of your website, it’s probably the only audio they’re listening to at the time and there’s a fair chance they don’t want to close it. In which case, do this:

  1. window.onbeforeunload =
  2.   -> "You're currently playing. Are you sure you want to leave?"
  3.   if playing()

The point of interest here is it’s “built-in”. You just return a string. You don’t, and shouldn’t, call confirm.

The other point is the isplaying() part! Breaking user expectations is not something to be done lightly.