<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>Pocket JavaScript</title>
	<subtitle>Blog by Nolan Lawson about JavaScript on mobile devices</subtitle>
	
	<link href="https://pockerjavascript.com/feed/feed.xml" rel="self"/>
	<link href="https://pockerjavascript.com/"/>
	<updated>2016-01-25T17:33:13Z</updated>
	<id>https://example.com/</id>
	<author>
		<name>Nolan Lawson</name>
		<email>nolan@nolanlawson.com</email>
	</author>
	
	<entry>
		<title>Composers and audiences</title>
		<link href="https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/"/>
		<updated>2016-01-25T17:33:13Z</updated>
		<id>https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/</id>
		<content type="html">&lt;p&gt;&lt;em&gt;(Yes, this post is about JavaScript. Please indulge the analogy for a bit.)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Imagine yourself as a young court composer in the 18th century. You&#39;ve just arrived in Vienna, fresh from the academy, with one goal in mind: to improve your craft, and to learn from the old masters. You&#39;ve heard the stunning operas of Mozart, the ponderous fugues of Bach, and you&#39;ve dreamed of wowing audiences with your own contributions to this storied art form.&lt;/p&gt;
&lt;img src=&quot;https://pockerjavascript.com/img/sanssouci.jpg&quot; alt=&quot;Classical painting: playing a flute in front of sheet music for an audience&quot; /&gt;
&lt;figcaption&gt;Source: &lt;a href=&quot;https://en.wikipedia.org/wiki/Frederick_the_Great_Playing_the_Flute_at_Sanssouci&quot;&gt;Wikimedia Commons&lt;/a&gt;&lt;/figcaption&gt;
&lt;p&gt;You&#39;re excited by recent advances to improve the sonority of instruments – after all, the violin&#39;s &lt;a href=&quot;https://en.wikipedia.org/wiki/F-hole&quot;&gt;F-hole&lt;/a&gt; was only perfected in your lifetime. You&#39;re also intrigued by the strange note systems described by explorers to the Far Orient, completely unlike the 12-note chromatic scale you learned in school. You&#39;ve even heard of the complex rhythms practiced in Africa, far more intricate than the lock-step percussion of standard European fare.&lt;/p&gt;
&lt;p&gt;So your first day on the job, you approach your &lt;a href=&quot;https://en.wikipedia.org/wiki/Kapellmeister&quot;&gt;Kapellmeister&lt;/a&gt; and excitedly ask: what new techniques are being developed in the court of today? What musical innovations will amaze and delight opera-goers in the coming years?&lt;/p&gt;
&lt;p&gt;The master sighs and places a hand on your shoulder. The landscape of modern composition, he explains, is an arduous one. The raging debate among composers today is on the proper use of sheet music.&lt;/p&gt;
&lt;p&gt;&amp;quot;You see,&amp;quot; he says, &amp;quot;we realized some time ago that annotations like &lt;em&gt;Pizzicato&lt;/em&gt; and &lt;em&gt;Allegro&lt;/em&gt; are too difficult for non-Italian speakers to understand. Furthermore, they clutter up the page, and they take too much time for the musicians to sight-read. So we are gradually replacing them with symbols that explain the same concept.&amp;quot;&lt;/p&gt;
&lt;img src=&quot;https://pockerjavascript.com/img/sheet.jpg&quot; alt=&quot;Photo of sheet music&quot; /&gt;
&lt;figcaption&gt;Via www.songsimian.com on &lt;a href=&quot;https://www.flickr.com/photos/186095195@N02/49430612328&quot;&gt;Flickr&lt;/a&gt; (&lt;a href=&quot;https://creativecommons.org/licenses/by/2.0/&quot;&gt;CC BY 2.0&lt;/a&gt;)&lt;/figcaption&gt;
&lt;p&gt;&amp;quot;Ah,&amp;quot; you say, a bit surprised at the dull subject matter. &amp;quot;That does make sense. Musicians should be able to perform at their peak potential, in order to better please audiences.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Yes yes,&amp;quot; the master waves his hand dismissively. &amp;quot;But unfortunately this creates an additional problem, which is that our existing scores need to be laboriously migrated over to the new system. Furthermore, not all composers agree on which system to use, so there are many competing and incompatible standards.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;That would certainly create problems for the musicians!&amp;quot; you admit. &amp;quot;And the composers as well.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Indeed,&amp;quot; the master says. &amp;quot;It also causes headaches with the newly-invented musical typewriter. Every year, there are updates to the typewriter design, and every year composers need to learn the new system, or hold steadfastly to their familiar one.&amp;quot; He shakes his head. &amp;quot;As a community, we are suffering from tool fatigue.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;But what about the music?&amp;quot; you say impatiently, despite yourself. &amp;quot;All of this is well and good for composers, but how are we improving the experience for audiences? They don&#39;t care a bit how we create the music, only how it sounds.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;My child,&amp;quot; the master says with a smile, &amp;quot;you have much to learn. The more efficiently we can &lt;em&gt;create&lt;/em&gt; our music, the better it will be in the end for audiences. The most important thing is to learn the &lt;em&gt;purest&lt;/em&gt; system for note-writing, which I will deign to teach you. Here, let me show you my typewriter, which is of course the most advanced on the market today…&amp;quot;&lt;/p&gt;
&lt;h2 id=&quot;composing-javascript&quot;&gt;Composing JavaScript &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/#composing-javascript&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The analogy is a bit labored, but this is how I feel about web development today.&lt;/p&gt;
&lt;p&gt;Every day, I&#39;m bombarded by tweets and articles touting one framework over another, always in terms of the tooling and the developer experience, with little regard for the &lt;em&gt;user&lt;/em&gt; experience. From reading Hacker News or EchoJS, you&#39;d think the most important parts of JavaScript were the tools, patterns, and philosophies. The fact that someone, somewhere, is actually interacting with pixels on a screen feels like a side effect.&lt;/p&gt;
&lt;p&gt;Of course, &lt;a href=&quot;https://medium.com/@ericclemmons/javascript-fatigue-48d4011b6fc4&quot;&gt;tool fatigue&lt;/a&gt; is a well-worn topic, but I&#39;m not just talking about that. I&#39;m also talking about the endless discussion – especially in vogue in the React/Redux community – about &amp;quot;action creators&amp;quot; and &amp;quot;subreducers&amp;quot; and &amp;quot;sagas&amp;quot; and abstractions that are so complex you need &lt;a href=&quot;https://code-cartoons.com/a-cartoon-intro-to-redux-3afb775501a6&quot;&gt;a cartoon version&lt;/a&gt; to understand it. All of this mental overhead is deemed necessary to keep our app code from growing into an unreadable spaghetti mess (or so it&#39;s argued). &lt;a href=&quot;https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/#footnotes&quot;&gt;[1]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Then of course, there are the competitor frameworks that &lt;a href=&quot;http://staltz.com/why-react-redux-is-an-inferior-paradigm.html&quot;&gt;boast about their own ideological purity&lt;/a&gt; compared to the prevailing model. The more I read, the more it starts to sound like a game of intellectual one-upsmanship: &amp;quot;Oh, I only use &lt;em&gt;immutable data&lt;/em&gt;.&amp;quot; &amp;quot;Oh, I only use &lt;em&gt;pure functions&lt;/em&gt;.&amp;quot; &amp;quot;Oh, I only use &lt;em&gt;organic shade-grown npm modules&lt;/em&gt; .&amp;quot; With all this highfalutin terminology, I can&#39;t tell sometimes if I&#39;m reading about a JavaScript framework or the latest juice cleanse.&lt;/p&gt;
&lt;h2 id=&quot;forgetting-about-the-user&quot;&gt;Forgetting about the user &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/#forgetting-about-the-user&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Of course, tools and patterns are important, and we should be talking about them. Especially when working with junior developers, it&#39;s good to enforce best practices and teach difficult concepts. None of this discussion would bug me, except that it seems like the experience of the users (you know, those weird non-programmers who actually &lt;em&gt;use&lt;/em&gt; your app) is getting lost in the shuffle.&lt;/p&gt;
&lt;p&gt;Paul Lewis has already written about this in &lt;a href=&quot;https://aerotwist.com/blog/the-cost-of-frameworks/&quot;&gt;&amp;quot;The Cost of Frameworks,&amp;quot;&lt;/a&gt; but it bears repeating. Your user does not give a damn how you built your app; they only care that 1) it works, and 2) it works quickly. I&#39;m disappointed that so much of this topic gets shoved under the umbrella of &amp;quot;performance,&amp;quot; and that we have to hammer home the point that &lt;a href=&quot;https://twitter.com/search?q=%23perfmatters&quot;&gt;&amp;quot;perf matters&amp;quot;&lt;/a&gt;, because in fact &amp;quot;performance&amp;quot; is just the closest translation we have in developer-speak to what users would call &amp;quot;good experience.&amp;quot; &lt;a href=&quot;https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/#footnotes&quot;&gt;[2]&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I spend a lot of time harping on performance – in my work at Squarespace, at JavaScript meetups, and in my blog – and it never ceases to amaze me that &amp;quot;performance&amp;quot; is such a dark art to so many developers. The truth is that you can discover most performance problems by simply testing on slower hardware.&lt;/p&gt;
&lt;p&gt;For instance, I&#39;m shocked at how many developers (newbies and experts alike) are still using CSS &lt;code&gt;top&lt;/code&gt; and &lt;code&gt;left&lt;/code&gt; rather than &lt;code&gt;transform&lt;/code&gt; to animate movement, even though the framerate difference is &lt;a href=&quot;https://youtu.be/zrkCr1FThn0&quot;&gt;crystal-clear&lt;/a&gt; once you test on something other than an 8-core MacBook Pro. (My personal favorite workhorses are a janky 2011-era &lt;a href=&quot;http://amzn.com/B005ZEF01A&quot;&gt;Galaxy Nexus&lt;/a&gt; and a cheap &lt;a href=&quot;http://amzn.com/B00P6FM23W&quot;&gt;Acer laptop&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;Note that I&#39;m not saying newbies should feel guilty for making this mistake; &lt;code&gt;top&lt;/code&gt;/&lt;code&gt;left&lt;/code&gt; is much more intuitive than &lt;code&gt;transform&lt;/code&gt;. However, that&#39;s exactly why we (the experts) should be making an effort to learn and pass on these sorts of optimization techniques to them, rather than the petty minutia of the framework-of-the-week.&lt;/p&gt;
&lt;h2 id=&quot;a-lost-art&quot;&gt;A lost art &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/#a-lost-art&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&#39;d be understandable if performance tricks like &lt;code&gt;transform&lt;/code&gt; were arcane due to their novelty, but a lot of it is well-established stuff that seems to be willfully ignored. For instance, offline tools like IndexedDB, WebSQL, and AppCache have been around for years (&lt;a href=&quot;https://hacks.mozilla.org/2010/06/beyond-html5-database-apis-and-the-road-to-indexeddb/comment-page-1/&quot;&gt;2010&lt;/a&gt;, &lt;a href=&quot;https://webkit.org/blog/126/webkit-does-html5-client-side-database-storage/&quot;&gt;2007&lt;/a&gt;, and &lt;a href=&quot;http://googlecode.blogspot.com/2009/04/gmail-for-mobile-html5-series-using.html&quot;&gt;2009&lt;/a&gt; respectively), yet most web developers I talk to are barely aware of them. The same goes for WebWorkers, which have made parallelism possible &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/workers/basics/&quot;&gt;since 2010&lt;/a&gt;, though you wouldn&#39;t know it from browsing most web sites.&lt;/p&gt;
&lt;p&gt;These are technologies that can &lt;em&gt;vastly&lt;/em&gt; improve the user experience of your webapp, either by reducing server round-trips (offline) or increasing UI responsiveness (parallelism). And yet it feels like many of us are more eager to learn about some hot new framework that improves our own &lt;em&gt;developer&lt;/em&gt; experience, rather than existing technologies that empower users.&lt;/p&gt;
&lt;p&gt;If I sound bitter about the lack of progress in these areas, it&#39;s because I am. Just last week I published &lt;a href=&quot;https://www.npmjs.com/package/pseudo-worker&quot;&gt;pseudo-worker&lt;/a&gt;, a WebWorker polyfill, because I could not find a decent one anywhere on npm or Github. (Yes, for WebWorkers: a six-year-old technology!) I&#39;ve also spent the last few years working on &lt;a href=&quot;http://pouchdb.com/&quot;&gt;PouchDB&lt;/a&gt; and related IndexedDB/WebSQL projects, and the most surprising part of my experience has been realizing just how little work is being done in this field. Often I find myself &lt;a href=&quot;https://gist.github.com/nolanlawson/11672431f0d219b96335&quot;&gt;filing bugs on browsers&lt;/a&gt; for implementation flaws that should have been uncovered years ago, if people were actually using this stuff.&lt;/p&gt;
&lt;p&gt;I keep waiting for web developers to &amp;quot;discover&amp;quot; these techniques (as &lt;a href=&quot;http://adaptivepath.org/ideas/ajax-new-approach-web-applications/&quot;&gt;Ajax was &amp;quot;discovered&amp;quot;&lt;/a&gt; in 2005), but I barely heard a peep from the blogosphere this year, except in my own niche circles. Instead, one of the most heralded web technologies of 2015 was &lt;a href=&quot;http://gaearon.github.io/react-hot-loader/&quot;&gt;hot loading&lt;/a&gt;, a tool that allows you to ignore the slow loading time of your app in order to increase your own developer efficiency. If there&#39;s a better example of a tool that privileges developers at the expense of users, I can&#39;t think of one.&lt;/p&gt;
&lt;h2 id=&quot;looking-forward&quot;&gt;Looking forward &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/#looking-forward&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There&#39;s still hope that we can reverse this trend. I am encouraged by the burgeoning excitement over &lt;a href=&quot;https://ponyfoo.com/articles/serviceworker-revolution&quot;&gt;ServiceWorkers&lt;/a&gt;, and the fact that my &lt;a href=&quot;http://www.pocketjavascript.com/blog/2015/11/23/introducing-pokedex-org&quot;&gt;&amp;quot;Introducing Pokedex.org&amp;quot;&lt;/a&gt; post actually drew some attention to the potential of &lt;a href=&quot;https://medium.com/@slightlylate/progressive-apps-escaping-tabs-without-losing-our-soul-3b93a8561955&quot;&gt;progressive webapps&lt;/a&gt;. I&#39;m even more excited that Malte Ubl, the head of the &lt;a href=&quot;https://www.ampproject.org/&quot;&gt;AMP project&lt;/a&gt; at Google, has declared 2016 to be &lt;a href=&quot;https://medium.com/@cramforce/2016-will-be-the-year-of-concurrency-on-the-web-c39b1e99b30f&quot;&gt;the year of concurrency on the web&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;These are all efforts to improve the experience of web users, even if they add a bit of complexity to our app code and build processes. And in fact, the two aren&#39;t mutually exclusive; we can build tools that help both developers and users – projects like &lt;a href=&quot;http://hood.ie/&quot;&gt;Hoodie&lt;/a&gt; and &lt;a href=&quot;https://www.talater.com/upup/&quot;&gt;UpUp&lt;/a&gt; are making great strides in this area. I also love the performance feats that React and Ember (especially &lt;a href=&quot;http://emberjs.com/blog/2015/05/05/glimmer-merging.html&quot;&gt;Glimmer&lt;/a&gt;) have managed to pull off, which are being pushed even further by &lt;a href=&quot;https://docs.google.com/document/d/1M9FmT05Q6qpsjgvH1XvCm840yn2eWEg0PMskSQz7k4E&quot;&gt;Angular 2&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Some of these problems, though, can only be improved with education. Developers need to make more of an effort to learn the web platform itself, and not rely on some framework&#39;s abstraction of it. Luckily, there are plenty of folks doing great work to increase developer awareness around topics of performance and user experience, and to show what the web is capable of today: &lt;a href=&quot;https://youtu.be/obtCN3Goaw4?list=PLNYkxOF6rcIBz9ACEQRmO9Lw8PW7vn0lr&quot;&gt;Paul Lewis&lt;/a&gt;, &lt;a href=&quot;https://youtu.be/GxOq1bnlZXk&quot;&gt;Rachel Nabors&lt;/a&gt;, &lt;a href=&quot;https://youtu.be/puOrC7cfjRI&quot;&gt;Tom Dale&lt;/a&gt;, &lt;a href=&quot;https://youtu.be/Kz_zKXiNGSE&quot;&gt;Jason Teplitz&lt;/a&gt;, and &lt;a href=&quot;https://youtu.be/okk0BGV9oY0&quot;&gt;Henrik Joreteg&lt;/a&gt; are some names that spring to mind. (All of the above links are videos, and all of them are worth watching!)&lt;/p&gt;
&lt;p&gt;Overall, I&#39;m hoping that web developers in 2016 will spend a bit less time navel-gazing over our processes, philosophies, and abstractions. These things are important for the day-to-day task of building and maintaining code, but they shouldn&#39;t distract us from the needs of the people we ultimately serve: the users.&lt;/p&gt;
&lt;h4 id=&quot;footnotes&quot;&gt;Footnotes &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/#footnotes&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;[1]&lt;/strong&gt; I meant no offense to Dan Abramov, Lin Clark, André Staltz, or anybody else trying to make our applications&#39; wiring easier to manage. This stuff is hard-hitting, computer-sciency work, and fun to think about! It&#39;s just not the whole story, which is why I wrote this piece.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;[2]&lt;/strong&gt; &amp;quot;Design&amp;quot; is another good translation, although I think design and performance are inextricably linked (e.g. 60FPS animations, smooth transitions between related screens, etc.).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Nick Colley, Jan Lehnardt, André Miranda, and Garren Smith for feedback on a draft of this blog post.&lt;/em&gt;&lt;/p&gt;
&lt;h4 id=&quot;update-26%2Fjan%2F2016&quot;&gt;Update 26/Jan/2016 &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2016/1/25/composers-and-audiences/#update-26%2Fjan%2F2016&quot;&gt;#&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;I was super harsh on React, Redux, and Cycle.js folks in this post, and got &lt;a href=&quot;https://twitter.com/dan_abramov/status/691976015594311680&quot;&gt;rightfully called out for it&lt;/a&gt;. So I should clarify: I know plenty of folks in those communities do care about performance, and that the end-user experience &lt;a href=&quot;https://medium.com/swlh/the-case-for-flux-379b7d1982c6&quot;&gt;motivated a lot of these tools in the first place&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;React pioneered things like isomorphic rendering, which is absolutely &lt;em&gt;huge&lt;/em&gt; for performance. Webpack made code-splitting easier. All of these things are awesome! I even think hot-loading is nifty. (As long as you&#39;re still sure to test the actual load time of your app.)&lt;/p&gt;
&lt;p&gt;We all want to write great software. That&#39;s why we got into this business in the first place. My point was just that I don&#39;t feel like I&#39;m hearing nearly enough discussions about the capabilities of the web platform, and how webapps can be pushed in interesting directions.&lt;/p&gt;
&lt;p&gt;It sometimes feels like we&#39;ve concluded there are no more worlds to conquer, and that we just need to figure out how to perfect the process of writing websites as they were written in ~2012. That would be a shame. There are some wild possibilities in the web today (not just around offline and parallelism; Jenn Simmons has &lt;a href=&quot;https://youtu.be/ZNpn7FBp_9U&quot;&gt;an awesome talk&lt;/a&gt; about CSS layouts that nobody&#39;s using). I just don&#39;t want our tools and abstractions to distract us from that.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Introducing Pokedex.org: a progressive webapp for Pokémon fans</title>
		<link href="https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/"/>
		<updated>2015-11-23T15:47:00Z</updated>
		<id>https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/</id>
		<content type="html">&lt;p&gt;The mobile web has a bad reputation these days. Everyone agrees it&#39;s slow, but there&#39;s no shortage of differing opinions on how to fix it.&lt;/p&gt;
&lt;p&gt;Recently, Jeff Atwood argued convincingly that &lt;a href=&quot;https://meta.discourse.org/t/the-state-of-javascript-on-android-in-2015-is-poor/33889&quot;&gt;the state of single-threaded JavaScript on Android is poor&lt;/a&gt;. Then Henrik Joretag &lt;a href=&quot;https://joreteg.com/blog/viability-of-js-frameworks-on-mobile&quot;&gt;questioned the viability of JavaScript frameworks on mobile altogether&lt;/a&gt;, saying that tools like Ember and Angular are just too bloated for mobile networks to bear. (See also &lt;a href=&quot;https://aerotwist.com/blog/the-cost-of-frameworks/&quot;&gt;these&lt;/a&gt; &lt;a href=&quot;http://tomdale.net/2015/11/javascript-frameworks-and-mobile-performance/&quot;&gt;posts&lt;/a&gt; for a good follow-up discussion.)&lt;/p&gt;
&lt;p&gt;So to recap: Atwood says the problem is single-threadedness; Joretag says it&#39;s mobile networks. And in my opinion, they&#39;re both right. As someone who does nearly as much Android development as web development, I can tell you first-hand that the network and concurrency are two of my primary concerns when writing a performant native app.&lt;/p&gt;
&lt;p&gt;Ask any iOS or Android developer how we make our apps so fast, and most likely you&#39;ll hear about two major strategies:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Eliminate network calls.&lt;/strong&gt; Chatty network activity can kill the performance of a mobile app, even on a good 3G or 4G connection. Staring at a loading spinner is not a good user experience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use background threads.&lt;/strong&gt; To hit a silky-smooth 60 FPS, your operations on the main thread must take less than 16ms. Anything unrelated to the UI should be offloaded to a background thread.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I believe the web is as capable of solving these problems as native apps, but most web developers just aren&#39;t aware that the tools are out there. For the network and concurrency problems, the web has two very good answers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;http://offlinefirst.org/&quot;&gt;Offline-first&lt;/a&gt; (e.g. &lt;a href=&quot;http://w3c.github.io/IndexedDB/&quot;&gt;IndexedDB&lt;/a&gt; and &lt;a href=&quot;https://ponyfoo.com/articles/serviceworker-revolution&quot;&gt;ServiceWorkers&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.html5rocks.com/en/tutorials/workers/basics/&quot;&gt;Web workers&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I decided to put these ideas together and build a webapp with a rich, interactive experience that&#39;s every bit as compelling as a native app, but is also &amp;quot;just&amp;quot; a web site. Following guidelines from the Chrome team, I built &lt;a href=&quot;http://pokedex.org/&quot;&gt;Pokedex.org&lt;/a&gt; – a &lt;a href=&quot;https://infrequently.org/2015/06/progressive-apps-escaping-tabs-without-losing-our-soul/&quot;&gt;progressive webapp&lt;/a&gt; that works offline, can be launched from the home screen, and runs at 60 FPS even on mediocre Android phones. This blog post explains how I did it.&lt;/p&gt;
&lt;h2 id=&quot;pok%C3%A9mon-%E2%80%93-an-ambitious-target&quot;&gt;Pokémon – an ambitious target &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/#pok%C3%A9mon-%E2%80%93-an-ambitious-target&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For those uninitiated to the world of Pokémon, a Pokédex is an encyclopedia of the hundreds of species of cutesy critters, as well as their stats, types, evolutions, and moves. The data is surprisingly vast for what is supposedly a children&#39;s game (read up on &lt;a href=&quot;http://bulbapedia.bulbagarden.net/wiki/Effort_values&quot;&gt;Effort Values&lt;/a&gt; if you want your brain to hurt over how deep this can get). So it&#39;s the perfect target for an ambitious web application.&lt;/p&gt;
&lt;div class=&quot;videowrap&quot;&gt;
    &lt;video style=&quot;max-width:100%;&quot; poster=&quot;https://pockerjavascript.com/img/DeliriousNeedyAnophelesmosquito.png&quot; controls=&quot;&quot; muted=&quot;&quot; width=&quot;400&quot; aria-describedby=&quot;video1&quot;&gt;
      &lt;source src=&quot;https://pockerjavascript.com/vid/DeliriousNeedyAnophelesmosquito.webm&quot; type=&quot;video/webm&quot; /&gt;
      &lt;source src=&quot;https://pockerjavascript.com/vid/DeliriousNeedyAnophelesmosquito.mp4&quot; type=&quot;video/mp4&quot; /&gt;
    &lt;/video&gt;
&lt;/div&gt;
&lt;div class=&quot;sr-only&quot; id=&quot;video1&quot;&gt;
  Video showing scrolling a list of pokemon, clicking on Pikachua and it shows stats for Pikachu.
&lt;/div&gt;
&lt;p&gt;The first issue is getting the data, which is easy thanks to the wonderful &lt;a href=&quot;http://pokeapi.co/&quot;&gt;Pokéapi&lt;/a&gt;. The second issue is that, if we want the app to work offline, the database is far too large to keep in memory, so we&#39;ll need some clever use of IndexedDB and/or ServiceWorker.&lt;/p&gt;
&lt;p&gt;For this app, I decided to use &lt;a href=&quot;http://pouchdb.com/&quot;&gt;PouchDB&lt;/a&gt; for the Pokémon data (because it&#39;s good at sync), as well as &lt;a href=&quot;https://github.com/mozilla/localForage&quot;&gt;LocalForage&lt;/a&gt; for app state data (because it has a nice key-value API). Both PouchDB and LocalForage are using IndexedDB inside a web worker, which means any database operations are &lt;a href=&quot;http://nolanlawson.com/2015/09/29/indexeddb-websql-localstorage-what-blocks-the-dom/&quot;&gt;fully non-blocking&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, it&#39;s also true that the Pokémon data isn&#39;t immediately available when the site is first loaded, because it takes awhile to sync from the server. So I&#39;m also using a fallback strategy of &amp;quot;local first, then remote&amp;quot;:&lt;/p&gt;
&lt;img src=&quot;https://pockerjavascript.com/img/diagram.png&quot; alt=&quot;Diagram showing an offline-first architecture where we try a local PouchDB first and fall back to the network, and PouchDB continually syncs with Cloudant&quot; /&gt;
&lt;p&gt;When the site first loads, PouchDB starts syncing with the remote database, which in my case is &lt;a href=&quot;http://cloudant.com/&quot;&gt;Cloudant&lt;/a&gt; (a CouchDB-as-a-service provider). Since PouchDB has a dual API for both local and remote, it&#39;s easy to query the local database and then fall back to the remote database if that fails:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; localDB&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;err&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;br /&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; remoteDB&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;&lt;br /&gt;  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;(Yes, I also decided to use &lt;a href=&quot;http://pouchdb.com/2015/03/05/taming-the-async-beast-with-es7.html&quot;&gt;ES7 async/await&lt;/a&gt; for this app, using &lt;a href=&quot;https://github.com/facebook/regenerator&quot;&gt;Regenerator&lt;/a&gt; and &lt;a href=&quot;http://babeljs.io/&quot;&gt;Babel&lt;/a&gt;. It adds &amp;lt; 4KB minified/gzipped to the build size, so it&#39;s well worth the developer convenience.)&lt;/p&gt;
&lt;p&gt;So when the site first loads, it&#39;s a pretty standard AJAX app, using Cloudant to fetch and display data. Then once the sync has completed (which only takes a few seconds on a good connection), all interactions become purely local, meaning they are much faster and work offline. This is one of the ways that the app is a &amp;quot;progressive&amp;quot; experience.&lt;/p&gt;
&lt;h2 id=&quot;i-like-the-way-you-work-it&quot;&gt;I like the way you work it &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/#i-like-the-way-you-work-it&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I also heavily incorporated &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/workers/basics/&quot;&gt;web workers&lt;/a&gt; into this app. A web worker is essentially a background thread where you can access nearly all browser APIs except the DOM, with the benefit being that anything you do inside the worker cannot possibly block the UI.&lt;/p&gt;
&lt;p&gt;From reading &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/workers/basics/&quot;&gt;the&lt;/a&gt; &lt;a href=&quot;http://ejohn.org/blog/web-workers/&quot;&gt;literature&lt;/a&gt; on web workers, you might be forgiven for thinking their usefulness is limited to checksumming, parsing, and other computationally expensive tasks. However, it turns out that Angular 2 is planning on an architecture where &lt;a href=&quot;https://docs.google.com/document/d/1M9FmT05Q6qpsjgvH1XvCm840yn2eWEg0PMskSQz7k4E&quot;&gt;nearly the entire application lives inside of the web worker&lt;/a&gt;, which in theory should increase parallelism and reduce jank, especially on mobile. Similar techniques have also been explored for &lt;a href=&quot;https://medium.com/@nsisodiya/flux-inside-web-workers-cc51fb463882#.ooz0ho5si&quot;&gt;Flux&lt;/a&gt; and &lt;a href=&quot;http://blog.runspired.com/2015/06/05/using-webworkers-to-bring-native-app-best-practices-to-javascript-spas/&quot;&gt;Ember&lt;/a&gt;, although nothing solid has been shipped yet.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The idea is to run basically the whole app in [a web worker], and send rendering instructions to the UI side.”&lt;/p&gt;
&lt;p&gt;— Brian Ford, Angular core developer&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(&lt;a href=&quot;https://twitter.com/briantford/status/649332944478171136&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Since I like to live on the bleeding edge, I decided to put this Angular 2 notion to the test, and run nearly the entire app inside of the web worker, limiting the UI thread&#39;s responsibilities to rendering and animation. In theory, this should maximize parallelism and milk that multi-core smartphone for all it&#39;s worth, addressing Atwood&#39;s concerns about single-threaded JavaScript performance.&lt;/p&gt;
&lt;p&gt;I modeled the app architecture after React/Flux, but in this case I&#39;m using the lower-level &lt;a href=&quot;https://github.com/Matt-Esch/virtual-dom&quot;&gt;virtual-dom&lt;/a&gt;, as well as some helper libraries I wrote, &lt;a href=&quot;https://github.com/nolanlawson/vdom-as-json&quot;&gt;vdom-as-json&lt;/a&gt; and &lt;a href=&quot;https://github.com/nolanlawson/vdom-serialized-patch&quot;&gt;vdom-serialized-patch&lt;/a&gt;, which can serialize DOM patches as JSON, allowing them to be sent from the web worker to the main thread. Based on &lt;a href=&quot;https://code.google.com/p/chromium/issues/detail?id=536620#c11&quot;&gt;advice from IndexedDB spec author Joshua Bell&lt;/a&gt;, I&#39;m also stringifying the JSON during communication with the worker.&lt;/p&gt;
&lt;p&gt;The app structure looks like this:&lt;/p&gt;
&lt;img src=&quot;https://pockerjavascript.com/img/diagram2.png&quot; alt=&quot;Diagram showing the web worker handling the actions, rendering virtual dom, and diffing, and the UI thread handling applying the patch, generating the view, and dispatching an action&quot; /&gt;
&lt;p&gt;Note that the entire &amp;quot;Flux&amp;quot; application can live inside the web worker, as well as the &amp;quot;render&amp;quot; and &amp;quot;diff&amp;quot; parts of the &amp;quot;render/diff/patch&amp;quot; pipeline, since none of those operations rely on the DOM. The only thing that needs to be done on the UI thread is the patch, i.e. the minimal set of DOM instructions to be applied. And since this patch operation is (usually) small, the serialization costs should be negligible.&lt;/p&gt;
&lt;p&gt;To illustrate, here&#39;s a timeline recording from the Chrome profiler, using a Nexus 5 running Chrome 47 on Android 5.1.1. The timeline starts from the moment the user clicks on a Pokémon in the list, which is when the &amp;quot;detail&amp;quot; panel is patched and then slides up into view:&lt;/p&gt;
&lt;img src=&quot;https://pockerjavascript.com/img/trace1.png&quot; alt=&quot;Trace showing user clicks, apply patch, compute FLIP animation&quot; /&gt;
&lt;p&gt;(The delay between applying the patch and calculating the FLIP animation is intentional; it&#39;s to allow the &amp;quot;ripple&amp;quot; animation to play.)&lt;/p&gt;
&lt;p&gt;The important thing to notice is that the UI thread is totally unblocked between the user tapping and the patch being applied. Also, the deserialization of the patch (&lt;code&gt;JSON.parse()&lt;/code&gt;) is inconsequential; it doesn&#39;t even register on the timeline. I also measured the overhead of the worker itself for a single request, and it&#39;s typically in the 5-15ms range (although it does occasionally spike to as much as 200ms).&lt;/p&gt;
&lt;p&gt;Now let&#39;s see what it looks like if I move those operations back to the UI thread, by removing the worker:&lt;/p&gt;
&lt;img src=&quot;https://pockerjavascript.com/img/trace2.png&quot; alt=&quot;Trace showing compute colors, queue IndexedDB operations, IndexedDB callbacks, render, diff, apply patch, compute FLIP animations&quot; /&gt;
&lt;p&gt;Whoa nelly, there&#39;s a lot of action happening on the UI thread! Besides IndexedDB, which introduces some slight DOM-blocking, there&#39;s also the rendering/diffing operation, which is considerably more expensive than the patching.&lt;/p&gt;
&lt;p&gt;You&#39;ll also notice that both versions take roughly the same amount of time (300-400ms), but the former blocks the UI thread way less than the latter. In my case, I&#39;m using GPU-accelerated CSS animations, so you won&#39;t notice much of a difference either way. But you can imagine that, in a more complex app, where there might be many simultaneous bits of JavaScript fighting for the UI thread (third-party ads, scroll effects, etc.), this trick could mean the difference between a janky UI and a smooth UI.&lt;/p&gt;
&lt;h2 id=&quot;progressive-rendering&quot;&gt;Progressive rendering &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/#progressive-rendering&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Another benefit of Virtual DOM is that we can pre-render the initial state of the app on the server side. I used &lt;a href=&quot;https://github.com/nthtran/vdom-to-html/&quot;&gt;vdom-to-html&lt;/a&gt; to render the first 30 Pokémon and inline that HTML directly in the page. (HTML in our HTML! what a concept.) To re-hydrate that Virtual DOM on the client side, it&#39;s as simple as using &lt;a href=&quot;https://github.com/nolanlawson/vdom-as-json&quot;&gt;vdom-as-json&lt;/a&gt; to build up the initial Virtual DOM state.&lt;/p&gt;
&lt;img src=&quot;https://pockerjavascript.com/img/pokedex.png&quot; alt=&quot;Pokedex.org with JavaScript disabled, it still works.&quot; /&gt;
&lt;figcaption&gt;Pokedex.org with JavaScript disabled.&lt;/figcaption&gt;
&lt;p&gt;I&#39;m also inlining most of the critical CSS and JavaScript, with non-critical CSS loaded asynchronously thanks to a &lt;a href=&quot;http://stackoverflow.com/a/32614409/680742&quot;&gt;pretty nifty hack&lt;/a&gt;. The &lt;a href=&quot;https://github.com/nolanlawson/pouchdb-load&quot;&gt;pouchdb-load&lt;/a&gt; plugin is also being leveraged for faster initial replication.&lt;/p&gt;
&lt;p&gt;For hosting, I&#39;m simply putting up static files on &lt;a href=&quot;https://aws.amazon.com/s3/&quot;&gt;Amazon S3&lt;/a&gt;, with SSL provided by &lt;a href=&quot;https://www.cloudflare.com/&quot;&gt;Cloudflare&lt;/a&gt;. (SSL is required for ServiceWorkers.) Gzip, cache headers, and SPDY are all handled automatically by Cloudflare.&lt;/p&gt;
&lt;p&gt;Testing in the Chrome Dev Tools with the network throttled to 2G, the site manages to get to &lt;code&gt;DOMContentLoaded&lt;/code&gt; in 5 seconds, with the first paint at around 2 seconds. This means that the user at least has &lt;em&gt;something&lt;/em&gt; to look at while the JavaScript is loading, vastly improving the site&#39;s perceived performance.&lt;/p&gt;
&lt;p&gt;The &amp;quot;do everything in a web worker&amp;quot; approach also helps out with progressive rendering, because most of the JavaScript related to UI (click animations, side menu behavior, etc.) can be loaded in a small initial JavaScript bundle, whereas the larger &amp;quot;framework&amp;quot; bundle is only loaded when the web worker starts up. In my case, the UI bundle weighs in at 24KB minified/gzipped, whereas the worker bundle is 90KB. This means that the page at least has some minor UI flourishes while the full &amp;quot;framework&amp;quot; is downloading.&lt;/p&gt;
&lt;p&gt;Of course, ServiceWorker is also storing all of the static &amp;quot;app shell&amp;quot; – HTML, CSS, JavaScript, and images. I&#39;m using a local-then-remote strategy to ensure the best possible offline experience, with code largely borrowed (well, stolen really) from Jake&#39;s Archibald&#39;s lovely &lt;a href=&quot;https://github.com/jakearchibald/svgomg&quot;&gt;SVGOMG&lt;/a&gt;. Like SVGOMG, the app also displays a little toast message to reassure the user that yes, the app works offline. (This is new tech; users need to be educated about it!)&lt;/p&gt;
&lt;div class=&quot;videowrap&quot;&gt;
    &lt;video style=&quot;max-width:100%;&quot; poster=&quot;https://pockerjavascript.com/img/offline-pokedex.png&quot; controls=&quot;&quot; muted=&quot;&quot; width=&quot;400&quot; aria-describedby=&quot;video2&quot;&gt;
      &lt;source src=&quot;https://pockerjavascript.com/vid/offline-pokedex.webm&quot; type=&quot;video/webm&quot; /&gt;
      &lt;source src=&quot;https://pockerjavascript.com/vid/offline-pokedex.mp4&quot; type=&quot;video/mp4&quot; /&gt;
    &lt;/video&gt;
&lt;/div&gt;
&lt;div class=&quot;sr-only&quot; id=&quot;video2&quot;&gt;
  Video showing &quot;ready to work offline,&quot; &quot;more info&quot; button, the button is clicked, a modal dialog says &quot;That&#39;s right
  a website that works offline.&quot;
&lt;/div&gt;
&lt;p&gt;Thanks to ServiceWorker, subsequent loads of the page aren&#39;t constrained by the network at all. So after the first visit, the entire site is available locally, meaning it renders in less than a second, or slightly more depending on the speed of the device.&lt;/p&gt;
&lt;h2 id=&quot;animations&quot;&gt;Animations &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/#animations&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since my goal was to make this app perform at 60 FPS even on substandard mobile devices, I chose Paul Lewis&#39; famous &lt;a href=&quot;https://aerotwist.com/blog/flip-your-animations/&quot;&gt;FLIP technique&lt;/a&gt; for dynamic animations, using only hardware-accelerated CSS properties (i.e. &lt;code&gt;transform&lt;/code&gt; and &lt;code&gt;opacity&lt;/code&gt;). The result is this beautiful &lt;a href=&quot;https://www.google.com/design/spec/material-design/introduction.html&quot;&gt;Material Design&lt;/a&gt;-style animation, which runs great even on my ancient Galaxy Nexus phone:&lt;/p&gt;
&lt;div class=&quot;videowrap&quot;&gt;
    &lt;video style=&quot;max-width:100%;&quot; poster=&quot;https://pockerjavascript.com/img/SlimySelfishHermitcrab.png&quot; controls=&quot;&quot; muted=&quot;&quot; width=&quot;400&quot; aria-describedby=&quot;video3&quot;&gt;
      &lt;source src=&quot;https://pockerjavascript.com/vid/SlimySelfishHermitcrab.webm&quot; type=&quot;video/webm&quot; /&gt;
      &lt;source src=&quot;https://pockerjavascript.com/vid/SlimySelfishHermitcrab.mp4&quot; type=&quot;video/mp4&quot; /&gt;
    &lt;/video&gt;
&lt;/div&gt;
&lt;div class=&quot;sr-only&quot; id=&quot;video3&quot;&gt;
  Video showing clicking Charmander and it animates to Charmander&#39;s stats page, animating the borders as well as the
  pokemon sprite itself.
&lt;/div&gt;
&lt;p&gt;The best part about FLIP animations is that they combine the flexibility of JavaScript with the performance of CSS animations. So although the Pokémon&#39;s initial state isn&#39;t pre-determined, we can still animate from anywhere in the list to a fixed position in the detail view, without sacrificing any frames. We can also run quite a few animations in parallel – notice that the background fill, the sprite movement, and the panel slide are three separate animations.&lt;/p&gt;
&lt;p&gt;The only place where I deviated slightly from Lewis&#39; FLIP algorithm was the animation of the Pokémon sprite. Because neither the source nor the target were positioned in a way that was conducive to animations, I had to create a third sprite, absolutely positioned within the body, as a façade to transition between the two.&lt;/p&gt;
&lt;h2 id=&quot;gotchas&quot;&gt;Gotchas &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/#gotchas&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Of course, any webapp can suffer from slowdowns if you&#39;re not careful to keep an eye on the Chrome profiler and constantly check your assumptions on a real device. Some of the issues I ran into:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;CSS sprites are great for reducing the payload size, but they slowed the app down to a crawl due to excessive memory usage. I ultimately went with base64 inlining.&lt;/li&gt;
&lt;li&gt;I needed a performant scrolling list, so I took some inspiration from &lt;a href=&quot;http://ionicframework.com/blog/collection-repeat/&quot;&gt;Ionic collection-repeat&lt;/a&gt;, &lt;a href=&quot;https://github.com/emberjs/list-view&quot;&gt;Ember list-view&lt;/a&gt;, and &lt;a href=&quot;https://developer.android.com/guide/topics/ui/layout/listview.html&quot;&gt;Android ListView&lt;/a&gt;, to build a simple &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; that &lt;em&gt;just&lt;/em&gt; renders the &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;s that are in the visible viewport, with stubs for everything else. This cuts down on memory usage, making the animations and touch interactions much snappier. And once again, all of the list computation and diffing is done inside of the web worker, so scrolling is kept buttery-smooth. This works with as many as 649 Pokémon being shown at once.&lt;/li&gt;
&lt;li&gt;Be careful what libraries you choose! I&#39;m using &lt;a href=&quot;http://muicss.com/&quot;&gt;MUI&lt;/a&gt; as my &amp;quot;Material&amp;quot; CSS library, which is great for bootstrapping, but sadly I discovered that it often wasn&#39;t doing the optimal thing for performance. So I ended up having to re-implement parts of it myself. For instance, the side menu was originally being animated using &lt;code&gt;margin-left&lt;/code&gt; instead of &lt;code&gt;transform&lt;/code&gt;, which leads to &lt;a href=&quot;https://youtu.be/Q-nxiBNxCA4&quot;&gt;janky animations on mobile&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Event listeners are a menace. At one point MUI was adding an event listener on every &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; (for the &amp;quot;ripple&amp;quot; effect), which slowed down even the hardware-accelerated CSS animations due to memory usage. Luckily the Chrome Dev Tools has a &amp;quot;Show scrolling perf issues&amp;quot; checkbox, which immediately revealed the problem:&lt;/li&gt;
&lt;/ol&gt;
&lt;img src=&quot;https://pockerjavascript.com/img/touch-listener.png&quot; alt=&quot;Screenshot of Chrome with the words touch listener on every pokemon button&quot; /&gt;
&lt;p&gt;To work around this, I attached a single event listener to the entire &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt;, which is responsible for animating the ripple effect on individual &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt;s.&lt;/p&gt;
&lt;h2 id=&quot;browser-support&quot;&gt;Browser support &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/#browser-support&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As it turns out, a lot of the APIs I mention above aren&#39;t perfectly supported in all browsers. Most notably, ServiceWorker is not available in Safari, iOS, IE, or Edge. (Firefox has it in nightly and will ship very soon.) This means that the offline functionality won&#39;t work in those browsers – if you refresh the page without a connection, the content won&#39;t be there anymore.&lt;/p&gt;
&lt;p&gt;Another hurdle I ran into is that &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=149953&quot;&gt;Safari does not support IndexedDB in a web worker&lt;/a&gt;, meaning I had to write a workaround to avoid the web worker in Safari and just use PouchDB/LocalForage over WebSQL. Safari also still has the 350ms tap delay, which I chose not to fix with the &lt;a href=&quot;https://github.com/ftlabs/fastclick&quot;&gt;FastClick hack&lt;/a&gt; because I know Safari will fix it themselves in &lt;a href=&quot;https://twitter.com/jaffathecake/status/659174357583814656&quot;&gt;an upcoming release&lt;/a&gt;. Momentum scrolling is also broken in iOS, for reasons I don&#39;t yet understand. (&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href=&quot;https://github.com/nolanlawson/pokedex.org/issues/4&quot;&gt;looks like&lt;/a&gt; it needs &lt;code&gt;-webkit-overflow-scroll: touch&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;Surprisingly, Edge and FirefoxOS both worked without a hitch (except for ServiceWorker). FirefoxOS even has the status bar theme colors, which is neat. I haven&#39;t tested in Windows Phone yet.&lt;/p&gt;
&lt;p&gt;Of course, I could have fixed all these compatibility issues with a million polyfills – &lt;a href=&quot;https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html&quot;&gt;Apple touch icons&lt;/a&gt; instead of &lt;a href=&quot;http://www.w3.org/TR/appmanifest/&quot;&gt;Web Manifests&lt;/a&gt;, &lt;a href=&quot;http://alistapart.com/article/application-cache-is-a-douchebag&quot;&gt;AppCache&lt;/a&gt; instead of ServiceWorker, FastClick, etc. However, one of my goals for this app was to make a high-quality experience with &lt;em&gt;progressive degradation&lt;/em&gt; for the less standards-compliant browsers. On browsers with ServiceWorker, the app is a rich, high-quality offline app. On other browsers, it&#39;s just a web site.&lt;/p&gt;
&lt;p&gt;And I&#39;m okay with that. I strongly believe that web developers need to push the envelope on this stuff, if we expect browser vendors to have any motivation to improve their implementations. To quote WebKit developer Dean Jackson, one of the reasons they didn&#39;t prioritize IndexedDB was because they &lt;a href=&quot;https://twitter.com/grorgwork/status/610905347306328065&quot;&gt;&amp;quot;don&#39;t see much use.&amp;quot;&lt;/a&gt; In other words, if there were a lot of high-quality sites that depended on IndexedDB, then WebKit would have been pushed to implement it. But developers didn&#39;t step up their game, so browser vendors just shrugged it off.&lt;/p&gt;
&lt;p&gt;If we only use features that work in IE8, then we&#39;re condemning ourselves to live in an IE8 world. This app is a protest against that mindset.&lt;/p&gt;
&lt;h2 id=&quot;todos&quot;&gt;TODOs &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/#todos&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are still more improvements to make to this app. Some unanswered questions for me, especially involving ServiceWorker:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;How to handle routing?&lt;/strong&gt; If I do it the &amp;quot;right&amp;quot; way with the HTML5 History API (as opposed to hash URLs), does that mean I need to duplicate my routing logic on the server side, the client side, &lt;em&gt;and&lt;/em&gt; in the ServiceWorker? Sure seems that way.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How to update the ServiceWorker?&lt;/strong&gt; I&#39;m versioning all the data I store in the ServiceWorker Cache, but I&#39;m not sure how to evict stale data for existing users. Currently they need to refresh the page or restart their browser so that the ServiceWorker can update, but I&#39;d like to do it live somehow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;How to control the app banner?&lt;/strong&gt; Chrome will show an &amp;quot;install to home screen&amp;quot; banner if you visit the site twice in the same week (with some heuristics), but I really like the way &lt;a href=&quot;http://flipkart.com/&quot;&gt;Flipkart Lite&lt;/a&gt; captures the banner event so that they can launch it themselves. It feels like a more streamlined experience.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;videowrap&quot;&gt;
    &lt;video style=&quot;max-width:100%;&quot; poster=&quot;https://pockerjavascript.com/img/pokedex-install-banner.png&quot; controls=&quot;&quot; muted=&quot;&quot; width=&quot;400&quot; aria-describedby=&quot;video4&quot;&gt;
      &lt;source src=&quot;https://pockerjavascript.com/vid/pokedex-install-banner.webm&quot; type=&quot;video/webm&quot; /&gt;
      &lt;source src=&quot;https://pockerjavascript.com/vid/pokedex-install-banner.mp4&quot; type=&quot;video/mp4&quot; /&gt;
    &lt;/video&gt;
&lt;/div&gt;
&lt;div class=&quot;sr-only&quot; id=&quot;video4&quot;&gt;
  Video showing an install banner saying &quot;Pokedex.org - add to home screen&quot;
&lt;/div&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/11/23/introducing-pokedex-org/#conclusion&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The web is quickly catching up on mobile, but of course there are always improvements to be made. And like any good Pokémaniac, I want &lt;a href=&quot;http://pokedex.org/&quot;&gt;Pokedex.org&lt;/a&gt; to be the very best, &lt;a href=&quot;https://www.youtube.com/watch?v=DqXlSwBIHFc&quot;&gt;like no app ever was&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So I encourage anyone to take a look at &lt;a href=&quot;https://github.com/nolanlawson/pokedex.org/&quot;&gt;the source on Github&lt;/a&gt; and tell me where it can improve. As it stands, though, I think &lt;a href=&quot;http://pokedex.org/&quot;&gt;Pokedex.org&lt;/a&gt; is a gorgeous, immersive mobile app, and one that&#39;s tailor-made for the web. My hope is that it can demonstrate some of the great features that the web of 2015 can offer, while also serving as a valuable resource for the Pokémon fan who&#39;s gotta catch &#39;em all.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Thanks to Jacob Angel for providing feedback on a draft of this blog post.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For more on the tech behind &lt;a href=&quot;http://pokedex.org/&quot;&gt;Pokedex.org&lt;/a&gt;, check out &lt;a href=&quot;https://gist.github.com/nolanlawson/d9e66349635452a95bb1&quot;&gt;my &amp;quot;progressive webapp&amp;quot; reading list&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>The quest for smooth scrolling</title>
		<link href="https://pockerjavascript.com/blog/2015/2/3/the-quest-for-smooth-scrolling/"/>
		<updated>2015-02-16T16:45:20Z</updated>
		<id>https://pockerjavascript.com/blog/2015/2/3/the-quest-for-smooth-scrolling/</id>
		<content type="html">&lt;p&gt;Back in 2012, when Facebook famously ditched HTML5 for fully native apps, &lt;a href=&quot;https://lists.w3.org/Archives/Public/public-coremob/2012Sep/0021.html&quot;&gt;the main problem they cited&lt;/a&gt; was a lack of smooth scrolling:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“This is one of our most important issues. It’s typically a problem on the newsfeed and on Timeline, which use infinite scrolling. [...] Currently, we do all of the scrolling using JS, as other options were not fast enough (because of implementation issues).”&lt;/p&gt;
&lt;p&gt;— Tobie Langel&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It should be clear why this was a dealbreaker for Facebook. If you want people to stay glued to their timelines, then you need a scrolling list that doesn&#39;t break a sweat. Otherwise the user&#39;s attention starts to drift pretty fast.&lt;/p&gt;
&lt;p&gt;This affects more than just Facebook, though. As any mobile developer knows, the &amp;quot;ginormous scrolling list&amp;quot; is a common UI pattern across a wide variety of apps. Even if you&#39;re not Facebook, you probably have some kind of list – of notes, tasks, beers, Pokémon, whatever – that figures heavily into your app&#39;s presentation.&lt;/p&gt;
&lt;p&gt;Recently Flipboard caused quite a stir by unveiling their &lt;a href=&quot;http://engineering.flipboard.com/2015/02/mobile-web/&quot;&gt;scrolling list implementation&lt;/a&gt;, which renders to canvas in order to achieve 60 FPS. My reaction was: &amp;quot;neat!&amp;quot; The reaction of the web intelligentsia &lt;a href=&quot;http://www.broken-links.com/2015/02/13/flipboard-com-idealism-vs-pragmatism/&quot;&gt;was&lt;/a&gt; &lt;a href=&quot;http://farukat.es/journal/2015/02/708-how-flipboard-chose-form-over-function-their-web-version&quot;&gt;a&lt;/a&gt; &lt;a href=&quot;https://twitter.com/jaffathecake/status/566129048972431360&quot;&gt;bit&lt;/a&gt; &lt;a href=&quot;https://twitter.com/Charlotteis/status/565821393489891328&quot;&gt;more&lt;/a&gt; &lt;a href=&quot;https://twitter.com/codepo8/status/566572801445097473&quot;&gt;mixed&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Achieve 60 FPS easily by rendering your sites with node.js and imagemagick as static images!&lt;/p&gt;
&lt;p&gt;— Christian Heilmann (@codepo8) &lt;a href=&quot;https://twitter.com/codepo8/status/566199581416112128&quot;&gt;February 13, 2015&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As an Android developer who only recently learned the web stack, I can see where Flipboard is coming from. I&#39;ve heard for years that HTML5 was the equal of native platforms, and yet every time I&#39;ve tried to write a PhoneGap or AppCache-powered web app, I&#39;ve always had fun, but ended up feeling a little disappointed.&lt;/p&gt;
&lt;p&gt;For instance, I recently built a prototype app using &lt;a href=&quot;http://ionicframework.com/&quot;&gt;Ionic&lt;/a&gt;. Overall I found it to be a great developer experience, but getting a scrolling list to perform at 60 FPS &lt;a href=&quot;http://nolanlawson.s3.amazonaws.com/www/ionic_list_perf/index.html&quot;&gt;turned out to be impossible&lt;/a&gt;. And this was despite the admirable efforts of the Ionic team, who developed &lt;a href=&quot;http://ionicframework.com/blog/collection-repeat/&quot;&gt;some very clever tricks&lt;/a&gt; to achieve even 45-50 FPS.&lt;/p&gt;
&lt;p&gt;So the Flipboard approach starts to look pretty attractive by comparison. The cry of the web advocates, however, is that we shouldn&#39;t sacrifice accessibility, copy-paste, &amp;quot;find in page,&amp;quot; &amp;quot;open in new tab,&amp;quot; or other classic browser features at the altar of 60 FPS.&lt;/p&gt;
&lt;p&gt;My point of comparison, however, is with native apps. And when, exactly, was the last time you used a native app that let you &amp;quot;find in page&amp;quot;? Or even copy-paste? Sometimes you can &amp;quot;share,&amp;quot; but such functionality is usually hobbled in comparison to the web experience.&lt;/p&gt;
&lt;p&gt;Native apps have long abandoned the kind of built-in DOM features that web advocates swoon over (with the exception of accessibility, which works out-of-the-box with TextViews). And yet, native apps are the &lt;a href=&quot;http://cdixon.org/2014/04/07/the-decline-of-the-mobile-web/&quot;&gt;reigning champions&lt;/a&gt; of user attention, especially when it comes to &amp;quot;ginormous scrolling list&amp;quot;-style apps. That speaks volumes about what people really value when they&#39;re flicking through tweets at the bus stop.&lt;/p&gt;
&lt;p&gt;The truth is that for a largely consumptive experience – which is what infinite scrolling embodies – 60 FPS is much more valuable than the interactive features like &amp;quot;find in page&amp;quot; or copy-paste. Admittedly, accessibility is harder to justify throwing under the bus, which is why even Flipboard acknowledged that &lt;a href=&quot;https://github.com/flipboard/react-canvas#accessibility&quot;&gt;they need to fix it&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;But amidst all the hand-wringing from web apologists, as well as &lt;a href=&quot;http://daringfireball.net/linked/2015/02/10/flipboard-web&quot;&gt;some gleeful jabs from the web&#39;s detractors&lt;/a&gt;, I found the most insightful response to the Flipboard fiasco to be Jacob Rossi&#39;s:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Apple&#39;s &amp;quot;animation triggers&amp;quot; proposal would enable the &lt;a href=&quot;https://twitter.com/Flipboard&quot;&gt;@flipboard&lt;/a&gt; scroll UX at 60FPS w/o throwing out accessibility &lt;a href=&quot;http://t.co/FDEjTMb6pV&quot;&gt;http://t.co/FDEjTMb6pV&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;— Jacob Rossi (@jacobrossi) &lt;a href=&quot;https://twitter.com/jacobrossi/status/565348172793667585&quot;&gt;February 11, 2015&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, the web can solve the problem of slow scrolling in the same way that it solved the problem of &lt;a href=&quot;http://www.pocketjavascript.com/blog/2015/2/2/smooth-animations-in-css&quot;&gt;slow animations&lt;/a&gt;. Just as CSS animations allowed us to achieve native-level performance by moving rendering off the main thread (where it blocks the DOM) and onto a background thread or the GPU (where it hums along nicely), the &lt;a href=&quot;https://lists.w3.org/Archives/Public/www-style/2014Sep/0135.html&quot;&gt;animation triggers proposal&lt;/a&gt; would move the responsibility for scrolling squarely to the browser.&lt;/p&gt;
&lt;p&gt;Trying to re-implement the browser&#39;s scrolling in JavaScript, as Ionic and other frameworks do, is simply a non-starter if we want to achieve 60 FPS. JavaScript blocks the DOM, and as Flipboard says, &amp;quot;if you touch the DOM in any way during [JavaScript] animation, you’ve already blown through your 16ms frame budget.&amp;quot;&lt;/p&gt;
&lt;p&gt;Flipboard&#39;s solution was to replace the DOM with GPU-powered canvas. But the real solution is to replace JavaScript scrolling with GPU-powered scrolling.&lt;/p&gt;
&lt;p&gt;For the time being, though, JavaScript scrolling is the best we&#39;ve got, unless we want to dip into canvas or WebGL experiments like Flipboard&#39;s. Personally I think their approach is pretty exciting, especially if it spurs browser vendors to finally solve the sorts of scrolling problems that Facebook identified way back in 2012.&lt;/p&gt;
&lt;p&gt;Of course, now Facebook has an even bolder experiment in &lt;a href=&quot;http://blog.reactnative.com/introducing-react-native/&quot;&gt;React Native&lt;/a&gt;, based on the presumption that, even at 60 FPS, WebViews just &amp;quot;feel&amp;quot; wrong. But that will have to wait for a future blog post.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Closing the UX gap</title>
		<link href="https://pockerjavascript.com/blog/2015/2/2/javascript-on-mobile-closing-the-ux-gap/"/>
		<updated>2015-02-03T05:42:18Z</updated>
		<id>https://pockerjavascript.com/blog/2015/2/2/javascript-on-mobile-closing-the-ux-gap/</id>
		<content type="html">&lt;p&gt;For JavaScript to be an attractive tool for mobile developers, it&#39;s not enough for it to offer a good developer experience. It also has to offer a good user experience.&lt;/p&gt;
&lt;p&gt;The UI should feel spry and peppy. Animations should zip. Screens should respond immediately to the user&#39;s touch. If there&#39;s a reason &lt;a href=&quot;http://www.reddit.com/r/funny/comments/w5fl8/all_glory_to_the_hypnophone/&quot;&gt;people love their phones so much&lt;/a&gt;, it&#39;s because mobile apps are very good at delivering on these promises.&lt;/p&gt;
&lt;p&gt;Historically, though, hybrid and web apps have lagged behind their native counterparts in the &amp;quot;peppy&amp;quot; department. Mark Zuckerberg famously griped that HTML5 &lt;a href=&quot;http://mashable.com/2012/09/11/html5-biggest-mistake/&quot;&gt;&amp;quot;just wasn&#39;t ready&amp;quot;&lt;/a&gt; – a phrase that still echoes in the minds of many mobile developers today.&lt;/p&gt;
&lt;p&gt;For the mobile web to be taken seriously, it needs to provide the same smooth performance that we&#39;ve come to expect from native apps. In short, it needs to close the UX gap.&lt;/p&gt;
&lt;img src=&quot;https://pockerjavascript.com/img/nolan-talk.jpg&quot; alt=&quot;Picture of the author in front of a projection saying Mobile HTML5 apps that can compete with native&quot; /&gt;
&lt;p&gt;I recently gave a talk at &lt;a href=&quot;http://brooklynjs.com/&quot;&gt;Brooklyn JS&lt;/a&gt; where I shared some tricks for building web and hybrid apps with near-native performance. It wasn&#39;t recorded, but you can read &lt;a href=&quot;http://nolanlawson.github.io/brooklyn-js-html5-mobile-apps/#/&quot;&gt;the full slides and speaker notes&lt;/a&gt; online.&lt;/p&gt;
&lt;p&gt;The slides themselves are kinda neat, because they contain the very CSS animations that I talk about in the presentation. So you can open it up on a mobile browser and see the difference between, say, &lt;a href=&quot;http://www.pocketjavascript.com/blog/2015/2/2/smooth-animations-in-css&quot;&gt;hardware-accelerated and non-accelerated animations&lt;/a&gt;. The &lt;a href=&quot;http://nolanlawson.github.io/brooklyn-js-html5-mobile-apps/fps_demo.html&quot;&gt;FPS demo&lt;/a&gt; is also fun to play with.&lt;/p&gt;
&lt;p&gt;Just don&#39;t judge me too harshly if you open the slides in IE or Safari – I didn&#39;t have enough patience to get WEBM video or flexbox working properly. The CSS animations should look lovely, though.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Smooth animations in CSS</title>
		<link href="https://pockerjavascript.com/blog/2015/2/2/smooth-animations-in-css/"/>
		<updated>2015-02-03T03:18:27Z</updated>
		<id>https://pockerjavascript.com/blog/2015/2/2/smooth-animations-in-css/</id>
		<content type="html">&lt;p&gt;Working on the Squarespace &lt;a href=&quot;https://play.google.com/store/apps/details?id=com.squarespace.android.blog&quot;&gt;Blog app for Android&lt;/a&gt;, one of the biggest challenges is that the app is half-native, half-web.&lt;/p&gt;
&lt;p&gt;My job is to make sure you can&#39;t tell which is which.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://pockerjavascript.com/img/web-native.png&quot; alt=&quot;Phone with arrows pointing to it, some saying native and others web&quot; /&gt;&lt;/p&gt;
&lt;figcaption&gt;Spoiler alert.&lt;/figcaption&gt;
&lt;p&gt;While trying to achieve this goal, one of the first things I learned is that animations with native-level performance – i.e. animations that don&#39;t stutter, jerk, or lag – can only be achieved with &lt;a href=&quot;http://www.html5rocks.com/en/tutorials/speed/high-performance-animations/&quot;&gt;hardware-accelerated CSS&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Trust me, I&#39;ve tried. The other methods don&#39;t even come close.&lt;/p&gt;
&lt;p&gt;Here&#39;s a video showing a JavaScript animation, which I rewrote using hardware-accelerated CSS transitions:&lt;/p&gt;
&lt;lite-youtube videoid=&quot;JkOdrvVXG80&quot; style=&quot;background-image: url(&#39;/img/youtube-thumbnail-1.jpg&#39;);&quot;&gt;
  &lt;div class=&quot;lty-playbtn&quot;&gt;&lt;/div&gt;
&lt;/lite-youtube&gt;
&lt;p&gt;And here&#39;s a regular, non-accelerated CSS transition, which I rewrote in the same way:&lt;/p&gt;
&lt;lite-youtube videoid=&quot;zrkCr1FThn0&quot; style=&quot;background-image: url(&#39;/img/youtube-thumbnail-2.jpg&#39;);&quot;&gt;
  &lt;div class=&quot;lty-playbtn&quot;&gt;&lt;/div&gt;
&lt;/lite-youtube&gt;
&lt;p&gt;Behold the power of 3D transforms! And yes, I&#39;m not actually using the z-axis, but it doesn&#39;t matter. Just consider &amp;quot;3D&amp;quot; to be the &amp;quot;open sesame&amp;quot; to coax the GPU into revealing its treasures.&lt;/p&gt;
&lt;p&gt;If you&#39;d like to get started with hardware-accelerated CSS, then you can take a look at this &lt;a href=&quot;http://bl.ocks.org/nolanlawson/6db863f1e513bab9e273&quot;&gt;sample widget&lt;/a&gt;, which is the same one from the first video. It works on all modern browsers, both desktop and mobile. (Note the hand-crafted flexbox shim and -webkit prefixes.)&lt;/p&gt;
&lt;p&gt;These videos were taken on a rather dated Galaxy Nexus running Android 4.2, so the performance improvement is crystal-clear. But in fact, you can also see the difference on more powerful devices, and even on desktop browsers. I actually first noticed the slow trashcan animation while playing with it on desktop Chrome.&lt;/p&gt;
&lt;p&gt;Believe me: if it&#39;s anything less than 60 frames per second, &lt;a href=&quot;http://vimeo.com/108331968&quot;&gt;your users will notice&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Bootup</title>
		<link href="https://pockerjavascript.com/blog/2015/2/2/bootup/"/>
		<updated>2015-02-03T01:05:55Z</updated>
		<id>https://pockerjavascript.com/blog/2015/2/2/bootup/</id>
		<content type="html">&lt;p&gt;I decided to start a new blog, about a subject that&#39;s become very fascinating to me: JavaScript on mobile devices.&lt;/p&gt;
&lt;p&gt;For a long time, the web platform has lagged behind native apps in terms of performance and functionality. However, as 2015 dawns, I think we&#39;re rapidly approaching a time when it will be viable, if not standard practice, to choose tools like JavaScript, HTML, and CSS over tools like Swift, Objective-C, and Java.&lt;/p&gt;
&lt;p&gt;I chose the name &amp;quot;Pocket JavaScript&amp;quot; for a few reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The domain wasn&#39;t taken.&lt;/li&gt;
&lt;li&gt;JavaScript in your pocket! It&#39;s self-explanatory.&lt;/li&gt;
&lt;li&gt;Many developers have &amp;quot;pocket&amp;quot; JavaScript expertise (in the sense of a &amp;quot;pocket ace&amp;quot; in Poker). We all know a little JavaScript, even if it&#39;s not our primary language.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-javascript%3F&quot;&gt;Why JavaScript? &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/2/2/bootup/#why-javascript%3F&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&#39;s the only language we can use in the browser. We&#39;re stuck with it. And recently, it&#39;s become &lt;a href=&quot;https://medium.com/@brianleroux/es6-modules-amd-and-commonjs-c1acefbe6fc0&quot;&gt;not such a bad little language&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With Node.js, JavaScript has already conquered the server side, but &lt;a href=&quot;http://www.visionmobile.com/product/developer-economics-q3-2014/&quot;&gt;most mobile developers&lt;/a&gt; still write their Android, iOS, and Windows Phone apps using native tools. Imagine, though, a pure-JavaScript stack, where code could be shared not only between client and server, but between mobile apps and the browser.&lt;/p&gt;
&lt;p&gt;However you may feel about JavaScript&#39;s aesthetic qualities, you&#39;ve gotta admit: the productivity gains would be enormous. Developers could write code for any number of &lt;a href=&quot;http://www.theonion.com/articles/report-90-of-waking-hours-spent-staring-at-glowing,2747/&quot;&gt;glowing rectangles&lt;/a&gt; without having to learn new languages or frameworks.&lt;/p&gt;
&lt;p&gt;This is a future I can get excited about. And &lt;a href=&quot;https://resin.io/blog/happy-18th-birthday-javascript/&quot;&gt;it&#39;s already happening&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;onward&quot;&gt;Onward &lt;a class=&quot;direct-link&quot; href=&quot;https://pockerjavascript.com/blog/2015/2/2/bootup/#onward&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So let&#39;s prepare for this future now. In this blog, you can look forward to a discussion of interesting web-related technologies, and how they might be used on your mobile phone or tablet.&lt;/p&gt;
&lt;p&gt;I, for one, welcome our new JavaScript overlords.&lt;/p&gt;
</content>
	</entry>
</feed>
