Skip to main content
Topic: Elk Progressive Web App (Read 104 times) previous topic - next topic
0 Members and 1 Guest are viewing this topic.

Elk Progressive Web App

What is a Progressive Web App?  You've probably spotted the talk here on Elk recently. In nutshell, a PWA isn't a native app installing fully on your mobile device.  It isn't just a web page either.  It's somewhere in between: a hybrid.  It installs files and scripts from your site to your device. During operation it works like a native app yet looks like your site. It even has your site's icon on the device homescreen! All this without going through app stores, sign ups, signatures, moon phases, wind shifts, and high seas pirates. Cool huh?

Great!!  I'm sold!!  How do I get this wonderful technology?  So glad you asked. The good news is it's easy.  And it's not.  Say what?  It's easy once you've met certain prerequisite criteria.  Your site must be served over an HTTPS connection.  OK, that's the tough one.  HTTPS is beyond the scope of this thread.  If you don't have it you really should look into it anyway....  The others are a Manifest and Service Worker must be utilized - but we will cover the how-to here.  ;)  So let's get started!

Note:  This is the result of badmonkeying around, and much hackering.  It's guaranteed not to be the best way to do this. The only claim here is I made it operational using this method on three Elk sites.  The hope is more knowledgeable people will add to this thread, thus improving this method.  I will update this post with such improvements.  Thanks in advance to those who contribute!    8)

The specs on my server: Nginx 1.13.9, PHP 7.2, MariaDB 10.2


Create the icons: You will need to create a series of png icons for the app.  It will need various sizes.  It is important to note the canvas areas must be square even if the image itself is not.  The sizes needed are: 48x48, 96x96, 144x144, 192x192, 256x256, and 512x512.  Next, in the webroot, create a folder called /app.  Upload these images to it.  Some people get creative with file structures.  Scope is critical here.  The directory needs to be in the webroot to work.

Here is an example of one of mine:  asd

Create the manifest: In the webroot, create a file named manifest.json.  Give it permissions similar to the other operational files in your forum.  Below is a sample of a basic manifest file you may copy and paste into your manifest.json:

Code: [Select]
{
  "version": "1.0.1",
  "short_name": "My Site!",
  "name": "Mine!!",
  "description": "My application",
  "icons": [
    {
      "src": "/app/AC48.png",
      "type": "image/png",
      "sizes": "48x48"
    },
     {
      "src": "/app/AC96.png",
      "type": "image/png",
      "sizes": "96x96"
    },
    {
      "src": "/app/AC144.png",
      "type": "image/png",
      "sizes": "144x144"
    },
    {
      "src": "/app/AC192.png",
      "type": "image/png",
      "sizes": "192x192"
    },
    {
      "src": "/app/AC256.png",
      "type": "image/png",
      "sizes": "256x256"
    },
    {
      "src": "/app/AC512.png",
      "type": "image/png",
      "sizes": "512x512"
    }
  ],
  "start_url": "/index.php",
  "display": "standalone",
  "theme_color": "#384556",
  "background_color": "#384556"
}

Change the name to your site name, etc.  Change the icon names.  "Standalone" is configurable as well, to something like "fullscreen", though I don't recommend it.  Theme and background colors can be tweaked to match your site theme.  These change the colors of the header bar and the color of the splash screen, respectively.

Create the Service Worker:  OK, *technically* the script does this when the page loads. What we're doing here is creating the js file which performs this role.  Once again comes the warning: this must go in the webroot.  Create a file named sw.js.  Same permissions as you gave manifest.json.

Code: [Select]
// use a cacheName for cache versioning
var cacheName = 'v1:static';

// during the install phase you usually want to cache static assets
self.addEventListener('install', function(e) {
    // once the SW is installed, go ahead and fetch the resources to make this work offline
    e.waitUntil(
        caches.open(cacheName).then(function(cache) {
            return cache.addAll([
      '/themes/default/css/index.css',
      '/themes/default/css/_besocial/index_besocial.css',
      '/themes/default/css/_besocial/custom_besocial.css',
      '/themes/default/scripts/jquery-ui-1.12.1.min.js',
      '/themes/default/scripts/jquery.sceditor.bbcode.min.js',
    ]).then(function() {
                self.skipWaiting();
            });
        })
    );
});

// when the browser fetches a url
self.addEventListener('fetch', function(event) {
    // either respond with the cached object or go ahead and fetch the actual url
    event.respondWith(
        caches.match(event.request).then(function(response) {
            if (response) {
                // retrieve from cache
                return response;
            }
            // fetch as normal
            return fetch(event.request);
        })
    );
});


Notice the comma delimited cache list.  The function here is upon first app use, the files are downloaded and stored in the cache so they are always locally available.  Therefore the app can retrieve them locally, saving data over the air.  That said, I'm not personally convinced this has great value.  PWAs are heavily Chrome based, which is known for obscene caching. Seems to be little point here.


Inject some script:  There may be a number of ways to do this.  I did it the easy/hack way.  I installed the Simple Ads add on:
http://addons.elkarte.net/feature/Simple-Ads.html.  In the Position List, enable Overall Header. In Add Ad, name your block Service Worker.  Paste this code:

Code: [Select]
<html>
<head>
<link rel="manifest" href="', $boardurl, '/manifest.json">
<meta name="theme-color" content="#384556">
<meta http-equiv="Content-Type" content="application/x-web-app-manifest+json"/>
<script>
if('serviceWorker' in navigator) {
  navigator.serviceWorker
           .register('/sw.js')
           .then(function() { console.log("Service Worker Registered"); });
}

</script>
</head>
</html>

^^change the theme color to match your theme color again. Check "Active". Check "Overall Header". Check all membergroups you'd like to be able to use the app.  Check all actions. Check all boards. Edit Ad. 

The above could be done with Simple Portal, or a hook.  I'm not an eloquent enough programmer to pull that off.  Maybe some help from eman or spuds?  ;D

A template edit:  There is one core code edit. I've tried to figure out how to incorporate it into the code block above. Nada so far.  Anyway, it's a one liner.  In /themes/default/index.template.php:

Find:
Code: [Select]
// Show all the relative links, such as help, search, contents, and the like.
echo '

Add after:
Code: [Select]
<link rel="manifest" href="', $boardurl, '/manifest.json">

Restart php and apache/nginx. You should be good to go on the server!


So what now? Apparently there is at least some PWA support with Firefox, perhaps other browsers.  Most assuredly this works with Chrome.  SSSOOOO....using Chrome as the example....login, browse your site.  If you have everything correct, after some time you should get a banner inviting you to add the site to your homescreen.  Accept, enjoy!  8)


What doesn't work?  https://www.elkarte.net/community/index.php?topic=5114.0

Re: Elk Progressive Web App

Reply #1
Good job @badmonkey! I love to try this but I'll create an addon for it instead. So it'll be easier to add and remove.