Progressive Web Apps

233 views
Skip to first unread message

Martin Weissenboeck

unread,
Dec 13, 2018, 4:09:21 AM12/13/18
to web2py-users
I am just learning how to write Progressive Web Applications (PWA). I think PWAs are a very important step towards app-like websites. There is a lot of good examples on developers.google.com. One example has the following structure:

webroot
|--images/
|--scripts/
|--styles/
|--favicon.ico
|--index.html
|--manifest.json
|--service-worker.js

I want to use web2py to manage the datatables. What would be the best way to combine the PWA file-tree with a web2py app?

I have found only one (?) discussion about this topic at https://groups.google.com/forum/#!topic/web2py/rHBfs1zFG44

But there are some new questions:
  • My web2py server manages a lot of applications and it seems, that the proposed solution accepts only one app with one service-worker.js and so on.
  • All scripts would be visible to everybody at http://mydomain.com/myapp/static/scripts. I think this not a good idea.
Any ideas, any hints?
Who has written PWAs with web2py?

By the way: my next stept would be to use Preact together with PWAs. But for now I want to go step by step...


Regards Martin


dirman

unread,
Nov 28, 2019, 8:22:37 AM11/28/19
to web2py-users

#view

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Hello World</title>
  <link rel="manifest" href="/pwa/manifest.json">
  <link rel="stylesheet" href="/pwa/static/css/style.css">
  <link rel="icon" href="/pwa/static/favicon.ico" type="image/x-icon" />
  <link rel="apple-touch-icon" href="/pwa/static/images/hello-icon-152.png">
  <meta name="theme-color" content="#DE3C4B" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="theme-color" content="white"/>
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="apple-mobile-web-app-title" content="Hello World">
  <meta name="msapplication-TileImage" content="/pwa/static/images/hello-icon-144.png">
  <meta name="msapplication-TileColor" content="#FFFFFF">
</head>
<body class="fullscreen">
  <div class="container">
    <h1 class="title">Hello World!</h1>
  </div>
  <script src="/pwa/main.js"></script>
</body>
</html>

Write functions to return the three files instead. Dont put actual files in static folder 

#controller
def manifest():
    response.headers['Content-Type'] = 'text/json'
    return  '''
{
  "name": "Hello World",
  "short_name": "Hello",
  "icons": [{
    "src": "/pwa/static/images/hello-icon-128.png",
      "sizes": "128x128",
      "type": "image/png"
    }, {
      "src": "/pwa/static/images/hello-icon-144.png",
      "sizes": "144x144",
      "type": "image/png"
    }, {
      "src": "/pwa/static/images/hello-icon-152.png",
      "sizes": "152x152",
      "type": "image/png"
    }, {
      "src": "/pwa/static/images/hello-icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    }, {
      "src": "/pwa/static/images/hello-icon-256.png",
      "sizes": "256x256",
      "type": "image/png"
    }, {
      "src": "/pwa/static/images/hello-icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }],
  "lang": "en-US",
  "start_url": "/pwa/",
  "display": "standalone",
  "background_color": "#DE3C4B",
  "theme_color": "#DE3C4B"
}
'''

def main():
    response.headers['Content-Type'] = 'text/javascript'
    return '''
window.onload = () => {
  'use strict';

  if ('serviceWorker' in navigator) {
    navigator.serviceWorker
             .register('/pwa/sw.js');
  }
}
    '''


def sw():
    response.headers['Content-Type'] = 'text/javascript'
    return '''
var cacheName = 'hello-pwa';
var filesToCache = [
  '/',
  '/pwa/',
  '/pwa/static/css/style.css',
  '/pwa/static/js/main.js'
];

/* Start the service worker and cache all of the app's content */
self.addEventListener('install', function(e) {
  e.waitUntil(
    caches.open(cacheName).then(function(cache) {
      return cache.addAll(filesToCache);
    })
  );
});

/* Serve cached content when offline */
self.addEventListener('fetch', function(e) {
  e.respondWith(
    caches.match(e.request).then(function(response) {
      return response || fetch(e.request);
    })
  );
});
'''


Access the page on http://localhost/pwa and  test locally using Devtools and not lighthouse. Would work fine as a WPA app 

David Zejda

unread,
Dec 4, 2019, 12:06:40 PM12/4/19
to web2py-users
Hi,

I use web2py to serve PWA, service worker for client-side caching and for proactive loading of contents which are likely to be requested in the next step.

In routes.py I have root_static = ['favicon.ico', 'robots.txt', 'service_worker.js'].

Per-app specific service worker. The script is visible to the client (which is common for client-side JS, isn't it?). If you don't like it you may consider something like https://javascript-obfuscator.org/ .

Layout like this:

<!DOCTYPE html>
<html>
<head>
    <title>{{=response.title}}</title>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="msapplication-tap-highlight" content="no">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">   
    <link rel="manifest" href="{{=URL('static','viewer_manifest.json')}}" />

    <!-- Add to homescreen for Chrome on Android -->
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="application-name" content=" ... ">
    <link rel="icon" sizes="192x192" href="{{=URL("static", "/images/icons/icon-192x192.png")}}">

    <!-- Add to homescreen for Safari on iOS -->

    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="apple-mobile-web-app-title" content=" ... ">
    <link rel="apple-touch-icon" href="{{=URL("static", "/images/icons/icon-192x192.png")}}">

    <!-- Tile icon for Win8 (144x144 + tile color) -->
    <meta name="msapplication-TileImage" content="{{=URL("static", "/images/icons/icon-144x144.png")}}">
    <meta name="msapplication-TileColor" content="#2196f3">

    <!-- Color the status bar on mobile devices -->
    <meta name="theme-color" content="#2196f3">

    <link rel="stylesheet" href="{{=URL('static','css/viewer.css')}}"/>
    <link rel="stylesheet" href="{{=URL('static','css/arrows.css')}}"/>
    <!-- icon generator https://app-manifest.firebaseapp.com/ -->
   
    <link rel="stylesheet" href="{{=URL('default', 'cust_static',args=('viewer.css',))}}"/>

    {{if 'cust_style' in response:}} {{=XML(response.cust_style)}} {{pass}}
</head>
<body>

<script src="{{=URL('static','js/jquery.js')}}"></script>   
<script src="{{=URL('static','js/fittext-flex.js')}}"></script>   

{{if 'cust_js' in response:}}<script>{{=XML(response.cust_js)}}</script> {{pass}}

{{include}}

{{block page_js}}{{end page_js}}

<script src="{{=URL('static','js/ct_viewer.js')}}"></script>

</body>
</html>

David
Reply all
Reply to author
Forward
0 new messages