Today’s Readings

With the incredibly powerful news that iOS Safari 9.1 will finally support the picture element, support will soon take a huge leap forward, making art direction implementations a much more available option!

There are a couple other features worth noting in the 9.1 release notes, including the removal of the hated 350ms tap delay, and adding support for CSS variables and the will-change CSS property!

Also pretty powerful news that AWS is now offering free SSL certificates!

And speaking of AWS, here are a few best-practices for using AWS’ IAM.

Yet another nice, simple, easy-to-follow “use Flexbox for your complex layout” demo. Though published by WPMU DEV, there is nothing specifically having to do with WordPress here, everything in the article is applicable everywhere…

And as long as we’re playing with Flexbox, the Flexbox Playground CodePen is an awesome way to play with, get to know, and be awed by, all the various flexbox properties and attributes… It’s almost too powerful to fully grasp, when you consider all the combinations you can create…

The great shows us How Tabs Should Work (UI tabs, not browser tabs). Considering his impressive list of requirements near the top of the article, a wonderful solution to a very common, and commonly-troubled, UI pattern! (Note that he even offers a non-jQuery version near the bottom!)

And while we’re re-thinking UI patterns, here is a great walk-through on the thinking of, and designing, a new mobile navigation menu for PlayStation.com. As the first commenter states, it is always nice to see the thought that goes behind design.

A very nice, easy-to-follow Part 1 of JavaScript Modules: A Beginner’s Guide. Looking forward to Part 2!

And since the previous article started talking about ES2015 (formerly ES6), this ES6 Cheatsheet might also be useful… :-)

The Responsive Breakpoints Generator certainly got a lot of attention in the last couple weeks, and deservedly so. This Smashing Magazine article does a nice job of explaining the problem this tool solves, and how to best go about using it.

A Gulp-Based External SVG Symbol Sprite Icon System. As the author, , admits, it’s a horrible title, but it’s a great article on the subject!

And sticking with Una for a sec, I have to admit that I understand very little of what she is saying in her dotCSS 2015 presentation, but the effects she gets solely using CSS Blend Modes, Filters and Gradients, are amazing

And finally, I have mentioned before that I basically have no interest in computer game playing. But I cannot deny the power of the technologies used, and the impressive visuals that are created within them. So if you are interested in game development, check-out this HTML 5 game development video series!

Happy reading,
Atg

Converting WordPress to Web App: Adding “Add to home screen” functionality

Welcome to the final installment of my Converting WordPress to Web App series, where I will finish converting this site from a standard WP website to a cache-enabled, offline-first, performance-optimized, installable Web App, that takes advantage of Build and Deployment processes, and sits safely revisioned in a Version Control repo.

These are the steps that I have taken thus far:

  1. Series Intro
  2. Adding Version Control
  3. Adding a Build Process
  4. Adding a Deployment Process
  5. Adding Caching and Offline Support
  6. Adding “Add to home screen” functionality (this post)

And now, on to…

Adding “Add to home screen” functionality

For the record, what we’re talking about here is getting this little pop-up onto a website, so users can add an icon to their device’s home screen, that basically acts like a bookmark to your website:

An example of an "Add to Homescreen" pop-up, as displayed in Chrome on Android
“Add to Homescreen” pop-up, as displayed in Chrome on Android. Image screen-captured from Increasing engagement with Web App install banners.

Exactly how to best go about this has changed a little over the years…

When the iPhone first came out, Apple told us how to add a special link and meta tag to our pages and make a specially-sized icon available. And when Android came out, they initially supported the same Apple-centric tags and methods. And Windows Phone created their own tags. Then every iPad seemed to require a new tag, and soon this turned into tag soup! Just take a scroll through Everything you always wanted to know about touch icons

But even though we developers did this, it was still up to the user to figure out if this was available on our sites and then figure out how to add the home screen icon on their device. And, naturally, that process varied from device-to-device, and all those methods were their own little version of a pain in the ass…

So instead, developers like the great figured out how to create a custom pop-up with some script to try to help your users do this. Which is nice, but is now frowned upon because there is no way to tell if a user has already installed your app or dismissed the pop-up. (You can of course set a cookie, but we all know they’re only so reliable.) So you ended up with the possibility of someone that did install the app, or dismissed it, still getting the pop-up.

The current best practice is nicely documented by Google, and involves just a few simple steps:

  1. Your site needs a manifest file, which is a simple, static JSON file in your root directory. Jeremy Keith offers his as a nice, simple example, though other sites claim that a "short_name" parameter is required, which is missing from Jeremy’s…
  2. Your site must have a registered Service Worker. Oddly, it can actually just be an empty JS file that does absolutely nothing, you just need to register one.
  3. Your site must be served via HTTPS. This is a requirement to register the Service Worker, and it just makes good sense.
  4. With all of the above in place, a user must visit your site twice over two separate days within two weeks. The idea here is that first-time visitors are not faced with “INSTALL ME!” style messaging, and if they come back in that period, then they probably like the site, so now let’s offer installation. (This makes testing pretty difficult, so Chrome offers a flag that bypasses this restriction; enable chrome://flags/#bypass-app-banner-engagement-checks.)

And that’s it, this just works. In Chrome. On Android. Only. Hopefully other browsers will start following some similar pattern, ideally based on the same simple requirements. But for now, this is the method I will be following. It is, after all, just another progressive enhancement item, to me. If you have a project that requires this feature, then I would recommend going with Matteo’s solution above.

Creating the manifest.json File

If you’re at all like me, reading the W3C spec on the Web App Manifest might be enough to put you off of this step. Instead, I once again started with and the manifest file he created for his site.

The only adjustment I made was adding the possibly-required "short_name"; here is my manifest.json:

{
    "lang": "en",
    "short_name": "Atg.com",
    "name": "Aaron T. Grogg's website",
    "icons": [
        {
            "src": "favicon-144.png",
            "sizes": "144x144",
            "type": "image/png"
        },
        {
            "src": "favicon-300.png",
            "sizes": "300x300",
            "type": "image/png"
        }
    ],
    "start_url": "/",
    "display": "browser",
    "background_color": "#ffffff",
    "theme_color": "#ffffff"
}

I think the only items worth really discussing are the "start_url" and the "display". The "start_url" tells the device which page to open when the icon is selected, and the "display" tells the device if it should open in a regular browser window (with visible controls, as I would like my site to), or one of the other three options.

With this file ready and added to my repo’s /dist directory, I need to add the following link tag to my site’s header.php file:

<link rel="manifest" href="manifest.json">

It is worth noting that the above link has only been supported in Chrome since version 39. Prior to that, since version 31, you would have needed the following code:

<meta name="mobile-web-app-capable" content="yes">

It is up to you if you want to add that as well.

Adding Service Worker and HTTPS

Since I already set-up a Service Worker in a previous installment in this series and set-up HTTPS in another previous post, that’s all there is to this installment!

So all that is left is to visit the site, either with the Chrome restriction-bypass flag enabled, or following the time period restrictions, and wait for the “Add to Home Screen pop-up to appear!

Miscellaneous Notes

The Google Chrome GitHub repo offers a slew of varying code samples that you can click through. The documentation for each is in the index.html file in each sample, sadly not in the readme.md files where it would have been more easily reviewable.

The Google Developers site offers another in-depth walk-through, though this one also deals with installing native apps, as well, so not everything applies to this topic. The FAQ section has a few good points worth being aware of, like how to prevent the banner from displaying and how to detect if a user tapped the “Add” button. It is currently not possible to know if the app is installed or force the appearance of the “Add” message.

In addition to Matteo’s JS script referenced above, he also offers that script nicely wrapped in an easily configurable WordPress plugin. So, again, if you need this functionality for a project, and you’re using WP, this might be a nice route!

Status Thus Far

This week’s installment completes this series. Just a little over a month ago, this was a standard WP website, where I made manual edits and uploaded them via FTP. There was no Build Process, no Deployment Process, and my code was not even in a repo!

Now, I edit files locally and commit them to my repo, where my continuous integration process automatically triggers a build process that performs file concatenation, minification, and optimization, removing unnecessary CSS prefixes from any CSS files I have, and adding prefixes that are still needed, before determining my site’s critical CSS and pushing that into a file, then deploying the resulting code base to my Stage server for review. When I’m happy with that, one click deploys to my Live server, where a Service Worker automatically caches necessary assets into the user’s browser to improve page load speed and provides offline access to the most recent posts on my site. Return Android/Chrome users are also offered the option of installing a link to my site on their home screen, just like a native app.

That’s a pretty huge improvement for this old site! :-)

You can see all of the changes that I have made by checking out the repo on GitHub. This will continue to be my working repo for this website, so things will continue to change as this site progresses. So if you are reading this much later than it was written, it may not look the way it seems it should; just let me know if you have any questions on anything you see!

Next Up

There are so many options that I have no idea what I might try to conquer next…

With a Service Worker installed, I could easily enable push notifications to notify users with the installed app of new postings…

I mentioned at the end of the last installment that I wish my cache list was dynamic, so maybe I will look into that…

I would also like to find a way for WordPress to automatically create WebP-versions of all the images I upload, so I could then also use Service Worker to send the better-compressed images to browsers that can support them…

I really should dig into all of the Gulp Tasks out there to see if I can improve my Build Process in any way…

So, yeah, the possibilities are pretty endless… But you can be sure that whatever I decide to tackle next, will be documented here. :-)

Thanks for joining me on this journey, and happy Web Apping,
Atg

Today’s Readings

HUGE news as Service Workers (and push notifications) land in Firefox 44! Let the revolution begin!

Meanwhile the Chrome DevTools Service Worker panel that Jake mentions landing in Canary, is now live in Chrome 48!

And as long as we’re adding new panels to Chrome DevTools, have a stroll through the new Security panel!

DevTools themes are a great idea, but it’s too bad there are so many steps to activate the feature, and then each theme change requires closing and re-opening DevTools… But more of a rub, simply cannot get it to work in OSX Chrome 48…

Anybody use <input type="date">? I typically do not, instead preferring to either use a plugin or roll-my-own validation. But why? Because of the woes that come with “native support”

A lot of great examples of “motion with meaning”!

And speaking of animation, here’s an interesting look at Web Animation Trends: 31 Top Websites Deconstructed.

And one more, smooth-scroll is a “simple vanilla JS script to animate scrolling to anchor links”… Nice!

Combining WordPress and Angular… I would not have thought about it, but I am intrigued…

Speaking of WordPress, let’s dig into The Concept of “Plugin Territory” in WordPress… Deep…

Anyone out there still think about SEO? If so, here is a slick Chrome Extension that examines the current page for SEO concerns or issues.

The Goldilocks Approach
A good starting point for design that takes device resolution out of the equation

Incomplete List of Mistakes in the Design of CSS. Very incomplete, but always comforting to know others see them too… ;-)

Learn CSS Layout. A nice round-up of all there is to know about the subject.

Or you can review these CSS Refresher Notes. Wow, this just goes on and on and on… But in a good way! :-)

And finally, truly responsive tables, by simply not using tables

Happy reading,
Atg

Converting WordPress to Web App: Adding Caching and Offline Support

Part five of my Converting WordPress to Web App series, as we convert this site from a standard WP website to a cache-enabled, offline-first, performance-optimized, installable Web App, that takes advantage of Build and Deployment processes, and sits safely revisioned in a Version Control repo.

The steps that I plan to take are listed below; each will become a link as I complete and publish that part of the series.

  1. Series Intro
  2. Adding Version Control
  3. Adding a Build Process
  4. Adding a Deployment Process
  5. Adding Caching and Offline Support (this post)
  6. Adding “Add to home screen” functionality

And now, on to…

Adding Caching and Offline Support

Rich offline experiences, periodic background syncs, push notifications— functionality that would normally require a native application—are coming to the web. Service workers provide the technical foundation that all these features will rely on.
Introduction to Service Worker

Being able to cache assets to reduce HTTP Requests is big, but being able to offer your content offline, and even handle background updates and push notifications, is humongous! In fact, this allows a typical website to do something a lot of Native Apps don’t allow me to do: work offline!

I started collecting links to Service Worker resources, but then stumbled across these two from the changelog, which pretty much did that already:

The Service Worker code

This step was pretty easy because I basically just stole Jeremy Keith’s Service Worker implementation… I really like how he used multiple caches for URLs, pages and images, and how he implemented cache limits for pages and images.

All that said, I did make the following edits:

  1. I changed some of the variable names & values to reflect my site, plus added an initial cache-buster value of 'CACHE_BUSTER', which I will update programmatically in just a bit.
    var cacheStorage = 'atg.com',
        cacheBuster = 'CACHE_BUSTER',
        version = cacheStorage + '.' + cacheBuster,
        staticCacheName = version + '.static',
        pagesCacheName = version + '.pages',
        imagesCacheName = version + '.images';
    
  2. The function called during the install event (updateStaticCache) contains all of the files that I want to cache; naturally my list differs from Jeremy’s. Note my inclusion of my cacheBuster variable in my JS and CSS URLs. Also, following Jeremy’s example, I have created a custom Offline page, which I also cache for any pages that are not cached, to prevent the browser’s default “No Internet connection” page; a nice touch!
    // these can be cached at any time...
    cache.addAll([
        '/about/',
        '/contact/',
        '/resume/',
        '/projects/'
    ]);
    // these must be cached for the Service Worker to complete installation
    return cache.addAll([
        '/wp-content/themes/atg/scripts-min.'+cacheBuster+'.js',
        '/wp-content/themes/atg/styles-min.'+cacheBuster+'.css',
        '/',
        '/offline/'
    ]);
    
  3. I also needed to prevent a few URLs from being cached (and thus being served from cache), essentially anything on the Admin-side; I lost a fair bit of work before I realized that I needed to do this…
    if ( request.url.indexOf('/wp-admin') !== -1 || request.url.indexOf('/wp-includes') !== -1 || request.url.indexOf('preview=true') !== -1 ) {
        return;
    }
    

With the Service Worker file created, I then needed to activate it; I added the following to my site’s scripts.js:

// check if Service Worker is supported
if ('serviceWorker' in navigator) {
    // register the Service Worker, must be in the root directory to have site-wide scope...
    navigator.serviceWorker.register('/serviceworker-min.js')
        .then(function(registration) {
            // registration succeeded :-)
            console.log('ServiceWorker registration succeeded, with this scope: ', registration.scope);
        }).catch(function(err) {
            // registration failed :-(
            console.log('ServiceWorker registration failed: ', err);
        });
}

Updating the Repo

With these two new files created, I needed to add them to my repo, and as I want my Build Process to minify them both, I added them to my /src/scripts directory.

I then added this block to my gulpfile.js:

gulp.task( 'scripts-serviceworker', function() {
    // grab all serviceworker js files
    return gulp.src( 'src/scripts/serviceworker*.js' )
        // check if source has changed since last build
        .pipe( plugins.changed( THEME_DIST_DIR ) )
        // concatenate files into a single files
        .pipe( plugins.concat( 'serviceworker-min.js' ) )
        // minify concatenated file
        .pipe( plugins.uglify() )
        // save files into root /dist directory for proper scope
        .pipe( gulp.dest( 'dist/' ) );
});

Note the * in the gulp.src. This is in case I ever add another component to the Service Worker, or decide to add a polyfill for something, and I am prepared for concatenation. Also note that I am putting the resulting, minified file into my repo’s root dist directory. Unfortunately, the file needs to reside there in order to have the entire site in its scope.

Updating the Cache-Buster

I mentioned above that I wanted to programmatically update the Service Worker cache-buster, and DeployBot provides a really slick way of doing that.

The configuration option that allows us to easily update the cache-buster string is called “Run shell commands after deployment”:

Sample shell command DeployBot can run after deployment completes.
DeployBot’s ‘Run shell commands after deployment’ section allows you to perform shell scripts after the deployment has completed.

Note the link below the code box that opens a side panel displaying variables that you can use within your shell commands.

I wanted to use the 8-digit commit string, but the '%COMMIT%' variable outputs the same full commit string as the '%REVISION%' variable, which seemed excessive; instead I chose to use the '%RELEASE_ID%' variable, which is a “Unique ID for the triggered deployment.” Sounds like that will work quite nicely! It will mean that each deployment nullifies any cache that my users might have, but if I deployed again, I must have updated something, right?

Now, after completing a deployment, DeployBot grabs my serviceworker-min.js file and replaces my placeholder 'CACHE_BUSTER' string with the unique '%RELEASE_ID%' string!

Almost Home…

However, since the '%RELEASE_ID%' string will never match the really clever Last-Modified date cache-buster that I implemented some time ago, that means that the URLs that are cached by my Service Worker will never match the URLs in my markup, meaning the whole cache-thing breaks…

So, quick patch: I created another 'CACHE_BUSTER' placeholder in my theme’s functions.php file and will have DeployBot update that string as well; the updated “Run shell commands after deployment” code block:

Shell commands to replace cache-buster placeholders
Updated ‘Run shell commands after deployment’ code block

Voila!

And with that, I have a working Service Worker that, in supporting browsers, caches a preset collection of files, including a custom Offline page, allowing my users to visit any of those pages while offline, and improves performance even when the user is online.

And for non-supporting browsers? Everything is exactly like it was before I started this week’s endeavor. (Okay, these users do download the Service Worker registration code that is now in my scripts.js file, which they will never use, but I think that’s a pretty small price for them to pay, for the benefit of so many others.)

Status Thus Far

This week’s installment certainly provides a major boost to the power of any site! The reduced HTTP Requests and the offline capabilities are awesome additions!

But one thing I do not like about this set-up is the “static” list of assets that I have to maintain; I do not like that I have to manually tell the Service Worker what to cache for me.

For this simple blog site, it isn’t so hard, but if I ran an online news site, I might want my readers to be able to open the home page each morning and have all of today’s front-page stories and their respective assets get cached so they could reliably read them on their way to work, regardless of their connectivity. But this would require manual updates to the serviceworker.js cache list every time a new story gets published… Pretty unrealistic.

Ideally I would have a script, either in my serviceworker.js, or in my PHP, that tracks the articles and their assets, then pulls them in and caches them, automagically… Something for “phase 2”, I guess… :-)

For now, as always, you can see where we are thus far by checking out the repo on GitHub. Since this will be my working repo for this entire conversion process, the repo will continue to change as this series progresses. So if you are reading this much later than it was written, it may not look the way it seems it should; just keep pushing through and eventually it will!

Next Up

Next up I will be Adding “Add to home screen” functionality. This feature is certainly not necessary for every project, it is kind of useless on non-mobile devices, and it will not even work on all mobile devices, it is a cool feature that might impress your boss or some client, so I thought it would be cool to add to the series. Also, when coupled with push notifications, it takes your web app even one step closer to looking and feeling like a Native App!

There really isn’t much to this step, but if you are “playing along at home”, you may want to check-out these articles:

  1. Google discussing the concept of “install as app” banners
  2. The Web App Manifest spec

Okay, that should be it!

Until then, happy Web Apping,
Atg

Today’s Readings

How’s your ES6 coming along? Mine, not so good. I really need to start working my way through ‘s How to Learn ES6

And to get started, here is an interesting piece on Const & Immutable Objects.

And another on ECMAScript 6’s destructuring gotcha!

Pretty slick Kindle-style Ebook pagination with just a little CSS

gives us just a taste of what Grid Layout and subgrids will bring us as support matures.

In the mean time, I continue to be impressed with the flexibility that Flexbox brings us

And if you’re more the “watch don’t read” kinda person, then this Axis of Flexbox video is just for you

It’s 2016 already, how are websites still screwing up these user experiences?!

Indeed. How?!?!

Not all that practical in-and-of-itself, but making things like Building a Killer iPhone Layout with CSS are fun ways to learn!

Neat trick for CSS object-fit fallback on Edge (and other browsers).

That is slick!

That deserves to be added to these 22 Essential CSS Recipes, some of which you will likely know, but others are freaking awesome!

Now here is something you don’t see everyday: someone supporting the use of more parallax

I love the tweet screengrab in this Leaner Responsive Images With Client Hints article… I also love the technique that solves the problem that Brad highlights…

And finally, I’m proud that I am still cycling to and from work, well into winter (though admittedly we are not seeing anything here in Germany like it looks like our friends and family back along the east coast of the US are (or the photos in this article show!)), but it can get pretty cold! So, if you’re still trying to give it a go, make sure you follow these tips for winter bicycle riding!

Happy reading,
Atg