Progressive Web Application

Progressive Web Apps (PWAs) are regular web pages that can look like traditional desktop applications, or like modern native mobile Apps by combining modern browsers features.

The main keys for a web application to be considered a PWA are:

  • Progressive: should not have technological or accessibility restrictions.

  • Responsive: screens need to adapt to any device, and still be fully usable.

  • Network independent: able to start without network, and aware of network failures

  • App like: look like a native application

  • Fresh: updates happen transparently to the user

  • Safe: secure connections

  • Discoverable: user knows the App by visiting a page

  • Re-engageable: background notifications invite users to come back to the application

  • Installable: can be installed in the device home-screen, and opened like other native apps

  • Linkable: users can send links to the application

Bakery as a PWA

Bakery fulfills most of the requirements for a Progressive Web App:

  • Its UI is responsive, accessible, and looks like a native application, it gets updates from server on new versions, and all the stages of the application have a linkable URL.

  • It comes with a manifest.json file that makes the App discoverable and installable, as well as with a service worker that facilitates certain parts of the App to be cached for offline.

  • Bakery can be started when the device is offline, noticing to the user about the issue, and loading the UI when it is online.

  • It prevents the user to interact with the UI when the network is down.

Discoverable and Linkable

We use Vaadin routing annotations so as each stage of the application has a unique URL that can be linkable.

In addition, Bakery provides a manifest.json file indicating to browsers that the page is an application, it also has the name of the application, colors and icons.

By changing these parameters, you can customize how the icon looks in the home-screen and task manager, as well as the splash-screen and background.

{
  "name": "Bakery",
  "short_name": "Bakery",
  "start_url": "login",
  "display": "standalone",
  "theme_color": "#227aef",
  "background_color": "#227aef",
  "icons": [
    {
      "src": "icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    ...
  ]
}

In the CustomBootstrapListener.java we announce to the web browser where the manifest is by modificating the bootstrap page:

public class CustomBootstrapListener implements BootstrapListener {
  @Override
  public void modifyBootstrapPage(BootstrapPageResponse response) {
    ...
    final Element head = response.getDocument().head();
    // manifest needs to be prepended before scripts or it won't be loaded
    head.prepend("<meta name=\"theme-color\" content=\"#227aef\">");
    head.prepend("<link rel=\"manifest\" href=\"manifest.json\">");
    ...
  }
}

Installable

The presence of a manifest.json and a Service-Worker, allows that the user will be prompted to install the App when visiting the web site a few times.

Tip
Chrome criteria for displaying the install banner is to register a service worker, to serve the page over HTTPS, and to provide name, short_name, start_url and 192x192 icon in manifest.json.

Once you have the app-icon installed on your home-screen, click on it. Bakery will open in full-screen like a native app, you can see a splash-screen when it is opening.

In the following image, you can compare the App running in a tablet when it is opened from the home screen - looking as native, or in the browser - looking as a standard web page.

Starting the App from Home Screen

App Like, and Responsiveness

Bakery utilizes a bunch of techniques to look as a native application, and to adjust to the device screen size.

  • A responsive Web components selection:

    • vaadin-grid for displaying data without consuming so much resources.

    • vaadin-dialog is used for displaying forms, this guarantees that we can control whether the form is shown as a modal layer, or in full screen.

    • vaadin-form to configure responsive steps based on the viewport.

    • vaadin-tabs is able to adapt to the available space an show navigation arrows in case.

    • vaadin-board a responsive component used in the dashboard.

  • Vaadin themes for small visual variants in the components.

  • CSS media queryes for fine control, and to set CSS properties based on screen size.

Responsiveness
Note
in Bakery, custom styling of a specific template is done in its file, but component theming and common for the App styles are gathered in the shared-style.css file.

Accessibility

By using vaadin-core-elements it is guaranteed that screens are accessible

  • vaadin-text-field and vaadin-password-field for accessible text inputs.

  • vaadin-dialog deals with trapping the focus in the overlay and much more.

  • vaadin-date-picker and vaadin-combo-box are specialized form-components accessible for everyone.

  • vaadin-tabs allows navigate and announce pages with keyboard or mouse.

  • vaadin-grid makes easy to navigate cells with the keyboard.

Offline

Starting the App when Offline

The way to make an application available when offline, is by providing a Service Worker. Bakery CustomBootstrapListener.java class, includes the necessary javascript code to register the script sw.js as a Service Worker.

public class CustomBootstrapListener implements BootstrapListener {
  @Override
  public void modifyBootstrapPage(BootstrapPageResponse response) {

    // Add service worker
    response.getDocument().body().appendElement("script")
      .text("if ('serviceWorker' in navigator) navigator.serviceWorker.register('sw.js')");

  ...
  }
}

The sw.js script has all the magic for determining what should be cached, and what should be done in case of a network failure.

The significant part in this file is the variables to define which files need to be cached and used when the application is offline:

// Important: update the version each time you change any of the files listed below
var version = 2;
// define your offline-page and assets used by it
var manifest = 'manifest.json';
var offlinePage = 'offline-page.html';
var offlineAssets = [
  'images/offline-login-banner.jpg'
]

In addition, the SecurityConfiguration class need to be updated with the list of files that should be ignored.

@EnableWebSecurity
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Override
  public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers(
        ...
        "/manifest.json",
        "/sw.js",
        "/offline-page.html",
        ...
    );
  }
}

Interacting with the App when Offline

Due to the nature of Vaadin, the UI is managed from server side, thus the application will be unusable when the server is unavailable.

In Bakery, we provide a mechanism to notice the user about the offline issue when it happens. It shows an advice that covers the screen and prevents user interaction. The notice will disappear as soon as the network becomes available.

This is performed in the main-view.html template. The significant blocks here is the html defining the message to show, and the code detecting network changes.

   ...

    <div class="offline" hidden$="[[online]]">
      ...
    </div>

   ...

  <script>
    class MainView extends Polymer.Element {
      ...
      ready() {
        super.ready();
        this.online = window.navigator.onLine;
        window.addEventListener('online', () => this.online = true);
        window.addEventListener('offline', () => this.online = false);
      }
      ...
    }
  <script>

In the next screenshot, you can view how the message is displayed in Bakery when you check or uncheck the offline box in browser devtools.

Offline Screen