The fu­ture of web apps

The gap be­tween na­tive apps and web apps is nar­row­ing. Here, Chris Mills puts the spot­light on pro­gres­sive web apps, and ex­plores how they can help our apps level up

net magazine - - CONTENTS -

Chris Mills walks through the tech­nolo­gies bring­ing the power of na­tive apps to the web

The ca­pa­bil­i­ties avail­able to web­sites and apps have changed a lot since the early days of static pages. Even in re­cent times we’ve seen many sig­nif­i­cant ad­vance­ments: na­tive an­i­ma­tions, sim­ple flex­i­ble lay­outs (finally), real 3D graphics and stream­ing video, to name but a few. But there is still more to do, es­pe­cially if the web is to com­pete ef­fec­tively with na­tive plat­forms.

Spec writ­ers and browser en­gi­neers have been look­ing at the fea­tures that make na­tive plat­forms and their apps so pop­u­lar, see­ing how the web matches up, and work­ing hard to fill any holes in the web plat­form’s ca­pa­bil­i­ties. Es­sen­tially it boils down to a hand­ful of killer fea­tures, some of which are pretty sim­ple to im­ple­ment, oth­ers not so much. The fol­low­ing isn’t an ex­haus­tive list, but it cov­ers the main ar­eas. Na­tive apps are:

In­stal­lable: Hav­ing the app avail­able on the de­vice and in­te­grated with the un­der­ly­ing OS feels good – even bet­ter if you have a nice lit­tle tap­pable icon on your home­screen, and the app opens full-screen or in its own chrome. It’s the sim­ple things, right?

Dis­cov­er­able: Us web nerds don’t re­ally like closed app stores, but we can’t deny they im­prove the ex­pe­ri­ence of find­ing apps – al­though some ar­gue that even the best closed app stores are fail­ing be­cause of over­crowd­ing.

Off­line: Web con­nec­tiv­ity feels ubiq­ui­tous in many parts of the world, but it can’t be re­lied on 100 per cent of the time. It is an­noy­ing to not be able to use an app at all just be­cause you are off­line, and it needn’t be that way any more.

En­gag­ing: Once you’ve got a user to use your app, half the bat­tle is over. But how do you keep them en­gaged and on top of the lat­est up­dates? Na­tive app devel­op­ers have long en­joyed the avail­abil­ity of push no­ti­fi­ca­tions for up­dat­ing users.

Speedy: Na­tive code per­forms bet­ter than web code, or so some say. But as you’ll read later on, the gap is clos­ing rapidly. How­ever, the web also has some par­tic­u­lar ben­e­fits. It is:

Link­able: It is pos­si­ble to link to a web app at a given URL.

Re­spon­sive: With tools like me­dia queries, you can cre­ate com­plex app lay­outs that work across a va­ri­ety of form fac­tors (ori­en­ta­tion, res­o­lu­tion, screen size, and so on). In fact, the web’s de­fault lay­out model is in­her­ently re­spon­sive, which makes it es­pe­cially good for han­dling text.

Data-cen­tric: With HTML to pro­vide se­man­tics and struc­ture, the web is great at han­dling data.

Pro­gres­sive: You can write web apps that give mod­ern browsers the lat­est shiny good­ness, while still pro­vid­ing an ac­cept­able ex­pe­ri­ence on legacy browsers.

Se­cure: The web pro­vides ca­pa­bil­i­ties for apps to be se­cure, with its sin­gle-ori­gin se­cu­rity model, and HTTPS. Cre­at­ing se­cure web apps has be­come even eas­ier thanks to ini­tia­tives such as Let’s En­crypt (see mzl.la/en­crypt for more info). We want to cre­ate a web that al­lows for the kind of killer fea­tures found in na­tive apps, but not at the ex­pense of the ba­sic things that it al­ready does re­ally well. This move­ment is termed pro­gres­sive web apps, and is be­ing cham­pi­oned by or­gan­i­sa­tions in­clud­ing Mozilla and Google.

Later on we’ll look at the new tech­nolo­gies that are en­abling such ad­vance­ments, but first let’s talk a bit about other ap­proaches to help­ing the web catch up to na­tive.

Note: What’s in­ter­est­ing is that na­tive app plat­forms are work­ing on clos­ing the gap with the web too, from the other direc­tion. For ex­am­ple, with Rube Gold­berg-es­que con­trap­tions that en­able deep link­ing.

What cam e be­fore

Apps with na­tive ca­pa­bil­i­ties aren’t a com­pletely new con­cept. For a start, there have been many pack­aged ‘web’ app for­mats ap­pear­ing in var­i­ous places – for ex­am­ple Chrome apps – which al­low ver­i­fied pack­ages to be in­stalled on a de­vice so they are us­able off­line, and have per­mis­sion to ac­cess de­vice hard­ware and the like.

We have had so-called ‘hy­brid app’ tools for a while, for ex­am­ple Cor­dova and Elec­tron. These al­low devel­op­ers to write apps us­ing web tech­nolo­gies, and then trans­late them into na­tive apps that will run on iOS, An­droid and so on. Tools like this are very pop­u­lar, but they re­quire sev­eral ver­sions of an app to be cre­ated and dis­trib­uted, and there are some lim­i­ta­tions on the func­tion­al­ity that such apps can sup­port. Not quite ‘write once, de­ploy any­where’ as we know it.

Also im­por­tant is the off­line-first move­ment. Ad­vo­cates have ex­per­i­mented with and evan­ge­lised the idea of cre­at­ing web apps that will run off­line by de­fault, and then con­nect to the net­work to re­ceive up­dates only if it is avail­able.

And be­fore mov­ing on, it is worth men­tion­ing the sin­gle-page apps move­ment. In this, one sin­gle HTML page acts as the app’s con­tainer and loads the dif­fer­ent views dy­nam­i­cally us­ing XHR (or sim­i­lar), with the aim of mak­ing web apps snap­pier and more re­spon­sive. This is the kind of app model sup­ported by pop­u­lar frame­works like Em­ber.js and An­gu­larJS and, along with off­line-first, forms the ba­sis of a large part of pro­gres­sive web apps.

In­stal­la­tion and dis­cov­erab il­ity

The first area of pro­gres­sive web apps we’ll look at is in­stal­la­tion and dis­cov­er­abil­ity. This is made pos­si­ble us­ing the web app man­i­fest, which is a JSON file con­tain­ing in­for­ma­tion about the web app, such as icons, name, and dis­play mode to use when open­ing the app: { "name": "My sam­ple app", "short­_­name": "My app", "start_url": "./? ut­m_­source= we­b_ap­p_­man­i­fest", "dis­play": "stand­alone", "icons": [{ "src": "images/ touch/ home­screen48. png", "sizes": "48x48", "type": "image/png" }] ...

We want a web that al­lows for the kind of killer fea­tures found in na­tive apps

This can be used to in­te­grate the app more with the un­der­ly­ing OS (icon on home­screen, opens fullscreen in­stead of in the browser app, and so on), and in ad­di­tion pro­vides bet­ter dis­cov­er­abil­ity on app list­ings – for ex­am­ple, it will ap­pear in search en­gine re­sults.

This in­for­ma­tion is al­ready used by Opera and Chrome on mo­bile for plat­form in­te­gra­tion, with Fire­fox sup­port fol­low­ing soon.

Off­line

The web’s off­line prob­lem has per­sisted for an in­cred­i­bly long time, con­sid­er­ing how sim­ple it ap­pears to be at first glance. The trou­ble is that im­ple­ment­ing an ef­fec­tive off­line tech­nol­ogy set is far from sim­ple. Storing an app’s data off­line is not too much of a prob­lem – mod­ern browsers have had APIs like In­dexedDB for a while now, with web stor­age be­ing sup­ported as far back as IE8.

As­set stor­age, on the other hand, is a dif­fer­ent ball game. For a while it looked like Ap­pCache was go­ing to solve this prob­lem, but it proved not to be. Far too much was assumed about the way an app would be set up, and the de­vel­oper didn’t have enough con­trol over what was hap­pen­ing.

Fast-for­ward to now, and we have Ser­vice Work­ers; a new tech­nol­ogy avail­able in Fire­fox, Chrome and Opera that al­lows devel­op­ers to write off­line apps in the same vein as Ap­pCache, plus a lot more be­sides. It is a much lower-level API, and con­se­quently the syn­tax is a lot more com­pli­cated, but it does give devel­op­ers a lot more power over how they want their Ser­vice Worker in­ter­ac­tions to work.

A Ser­vice Worker takes the form of a chunk of JavaScript writ­ten in a sep­a­rate file and run­ning in a spe­cial worker thread. It acts as a proxy server, sit­ting in be­tween the net­work and your app (and the browser). When a re­quest is made for an as­set, the Ser­vice Worker can in­ter­cept it and cus­tomise the re­sponse be­fore it is sent back to the browser to be used.

To use a Ser­vice Worker, you first need to reg­is­ter it by run­ning nav­i­ga­tor.ser­viceWorker.reg­is­ter() in the main thread. nav­i­ga­tor.ser­viceWorker.reg­is­ter('sw.js') .then(func­tion(reg) { // Do some­thing to ini­tialise app }); Then in­stall the app us­ing an in­stall event lis­tener over in the Ser­vice Worker thread. This of­ten in­volves storing all the app’s essential as­sets us­ing the Cache API (which in­ci­den­tally can be used in­de­pen­dently of Ser­vice Work­ers): this.ad­dEven­tLis­tener('in­stall', func­tion(event) { event.wait­Un­til( caches.open('v1').then(func­tion(cache) { re­turn cache.ad­dAll([ '/sw-test/', '/sw-test/in­dex.html',

Next, use a fetch event lis­tener in the Ser­vice Worker to fire code when­ever a re­quest hap­pens. This al­lows devel­op­ers to cus­tomise the re­sult­ing re­sponse. So a de­vel­oper could cache each re­quest for files that don’t change much (such as the UI shell) in the in­stall step, and then serve the ver­sions stored off­line in the cache when they are re­quested, in­stead of the net­work ver­sion. Bingo, off­line apps!

User re-en­gage­ment

Na­tive plat­forms have long re­lied on push mes­sag­ing – the abil­ity to push a mes­sage from the server to the client to tell a user that some­thing has changed, or that some­thing new is avail­able – even when the app is not open. Maybe a news app wants to share break­ing news with the user? Or per­haps your Poké­mon is bored and wants some at­ten­tion? Well, thanks to the web Push API, we now have this ca­pa­bil­ity for web apps too.

To use web push, a Ser­vice Worker must be in­stalled and ac­tive on your app’s page(s), as ex­plained pre­vi­ously. Then, we sub­scribe to the

Ser­vice Work­ers are a new tech­nol­ogy that al­lows devel­op­ers to write off­line apps

nav­i­ga­tor.ser­viceWorker.ready.then(func­tion(reg) { reg.pushMan­ager.sub­scribe({userVis­i­bleOnly: true}) .then(func­tion(subscription) { // Update UI, etc. in light of subscription // Update sta­tus to sub­scribe cur­rent user on server var end­point = subscription.end­point; var key = subscription.getKey('p256dh'); This method re­turns a prom­ise that re­solves with a subscription ob­ject. This ob­ject has an end­point prop­erty (which con­tains a unique URL point­ing to a push server), and a getKey() method, which can be used to gen­er­ate a pub­lic key for en­cryp­tion pur­poses. You’ll need to ac­cess both of these, then send the re­sults to your app’s server.

To send a push mes­sage on the server, make a re­quest to the end­point URL. This causes the push server to send a mes­sage to the app’s Ser­vice Worker. If you want to send data along with the push mes­sage, it must be en­crypted us­ing the key. Push mes­sage data cur­rently only works on Fire­fox, but Blink-based browsers shouldn’t be far be­hind.

The Ser­vice Worker lis­tens for a push mes­sage us­ing a push event han­dler. Once a push event is fired, you can ac­cess the mes­sage data us­ing the event ob­ject’s data prop­erty. Then you can re­spond to the mes­sage how­ever you like – for ex­am­ple by fir­ing a no­ti­fi­ca­tion, or send­ing a chan­nel mes­sage back to the main thread to update your app in some way. self.ad­dEven­tLis­tener('push', func­tion(e) { var obj = e.data.json(); // Re­spond to the push mes­sage in some way

// e.g. a no­ti­fi­ca­tion or chan­nel mes­sage });

Note: Most of the Ser­vice Work­ers fam­ily of tech­nolo­gies (Push and so on) en­joy rea­son­able sup­port across Chrome and Fire­fox, with other browsers con­sid­er­ing them care­fully. Push data only works in Fire­fox at the time of writ­ing.

Per­forma nce

Per­for­mance has long been a sore point be­tween web apps and na­tive apps, with na­tive devel­op­ers dis­miss­ing the web’s per­for­mance ca­pa­bil­i­ties. But the di­vide is sig­nif­i­cantly nar­rower in the mod­ern day, with much faster JavaScript en­gines in browsers, and fast in-browser code for run­ning things like an­i­ma­tions and 3D graphics, which can in­creas­ingly take ad­van­tage of avail­able GPU power.

In ad­di­tion, we are now ca­pa­ble of tran­spiling na­tive code (such as C++) across to JavaScript, us­ing tech­nolo­gies like Em­scripten. When we say JavaScript here, we are talk­ing about asm.js, a highly-op­ti­mis­able sub­set of JavaScript that can take ad­van­tage of AOT com­pi­la­tion tech­niques to pro­vide near-na­tive per­for­mance. This has proved so pop­u­lar that it is be­ing sup­ported in not only Fire­fox, but Chrome and Edge too, and asm.js/web has been added as a pub­lish­ing tar­get for pop­u­lar 3D en­gines Unity and Un­real.

And the next gen­er­a­tion is on its way – a num­ber of browser ven­dors are col­lab­o­rat­ing on spec­c­ing out and im­ple­ment­ing We­bAssem­bly, which will do a sim­i­lar thing to Em­scripten, but in a faster, more stan­dard, more per­for­mant way.

It will use a for­mat called wasm, rather than asm.js. Given that it will have a con­crete spec, we should be able to rely on com­pil­ers out­putting valid wasm, and browsers then run­ning that out­put con­sis­tently, re­gard­less of which com­piler cre­ated it. Watch this space.

Con­clu­sion

As you can see, the web is con­tin­u­ing to evolve, with some ex­cit­ing new tech­nolo­gies de­signed to ad­dress some of the re­main­ing short­com­ings our beloved plat­form has tra­di­tion­ally suf­fered, as well as boast­ing even bet­ter per­for­mance. These will al­low web apps to stand proud be­side na­tive apps, while not los­ing sight of what made the web great to be­gin with.

There are some ex­cit­ing new tech­nolo­gies de­signed to ad­dress the web’s short­com­ings

Pokedex.org Nolan Law­son’s Pokedex.org pro­vides a great ex­am­ple of a pro­gres­sive web app that is also a huge amount of fun!

Kana This ( getkana.com/

app) is a use­ful web app for any­one wish­ing to learn Japanese Kana char­ac­ters

Apache Cor­dova Cor­dova gets us some of the way across the web/ na­tive di­vide by al­low­ing us to write apps in web code and then pro­duce na­tive app ver­sions

Top left Tap­ping on a desk­top icon to open your favourite app is a key part of na­tive app UX; the web app man­i­fest is bring­ing this to web apps, too

Top right Har­ald Kirschner’s chro­matic tuner app ( netm.ag/chro­matic-282) is a nice pro­gres­sive ex­am­ple that works well on desk­top or a mo­bile de­vice

push ser­vice. This can be done by us­ing Ser­viceWork­erRegis­tra­tion.pushMan­ager.sub­scribe() , as shown be­low: }); up­dateS­ta­tus(end­point,key,'sub­scribe'); })

Left Sys­tem no­ti­fi­ca­tions are a great way to pro­vide users with up­dates

Right The above di­a­gram il­lus­trates the life­cy­cle of a Ser­vice Worker in­stal­la­tion

Plat­form sta­tus This app from Mozilla ( plat­form

sta­tus.mozilla.org) pro­vides progress in­for­ma­tion on the im­ple­men­ta­tion of mod­ern web APIs in browsers

Newspapers in English

Newspapers from Australia

© PressReader. All rights reserved.