Progressive Web Application in Liferay : Part 1

Capable, Reliable and Installable

A Progressive Web Applications (PWA) attempt to make use of the advanced features of modern web browsers and combine it with the native application user experience.  A Progressive Web Applications look and behave like mobile native app with lots of additional capabilities. Below are feature comparison between PWA, Web App and Native App.

If you like know more about PWA, there are some good articles available on web.dev with details explanation of PWA features and characteristics. 

Any web applications (including Liferay portal) can be easily converted into Progressive Web Applications. In this blog post, you will learn how to make installable PWA of any liferay portal.

Installable

To make any web application installable, it should meet following criteria: 
1. The web app is not already installed
2. Hosted on HTTPS (or localhost)
3. Includes a Web App Manifest
4. Registers a service worker with a functional fetch handler

Web App Manifest

In Liferay, we can add Web App Manifest file in theme. Create an manifest.json file in your theme with following details:

{
  "short_name": "My Portal",
  "name": "My Portal: PWA",
  "description": "My Portal: PWA desc",
  "icons": [
    { "src": "/image-path/my-portal-logo.png",
      "type": "image/png",
      "sizes": "144x144"
    }
  ],
  "start_url": "/",
  "background_color": "#3367D6",
  "display": "standalone",
  "scope": "/",
  "theme_color": "#3367D6",
  "orientation": "portrait",
  "background_color": "#ffffff"
}

And add manifest.json path in your theme's head tag like:

<head>
    <title>${the_title} - ${company_name}</title>
    <meta content="initial-scale=1.0, width=device-width" name="viewport" />
    <@liferay_util["include"] page=top_head_include />
    <link rel="manifest" href="${templates_folder}/manifest.json">
</head>

Service Worker

Now we need Register service worker. For service worker registration, you need to create a javascript file(sw.js) in your theme with following code:

self.addEventListener('fetch', function(e) {
  e.respondWith(
    caches.match(e.request).then(function(response) {
      return response || fetch(e.request);
    })
  );
});

The javascript file name can be anything. Add following javascript in your portal_noraml.ftl below the body tag :

<script>

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('${javascript_folder}/sw.js', { scope: '/' }).then(function(registration) {
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, function(err) {
      console.log('ServiceWorker registration failed: ', err);
    });
  });
}
</script>

 

So is it enough for PWA? The answer is no. If you deploy theme and visit page on your browser, you will see following error : 

Registration failed with SecurityError: Failed to register a ServiceWorker: The path of the provided scope ('/practice/foopage/') is not under the max scope allowed ('/static/mod/practice/'). Adjust the scope, move the Service Worker script, or use the Service-Worker-Allowed HTTP header to allow the scope.

Service workers can only intercept requests originating in the scope of the current directory that the service worker script is located in and its subdirectories see more details developer.mozilla.org and stackoverflow.com. To fix this issue, we need to add Service-Worker-Allowed http header for sw.js. You can write a servlet filter and add following code in your servlet filter: 

response.addHeader("Service-Worker-Allowed", "/");

If your application running behind web server, you can also add this header on web server level like for Apache 2.4, you need to add following line :

Header always set Service-Worker-Allowed "/"

That all you need to do for PWA enablement in Liferay portal.

In next blog post, I will write about offline uses(caching), push notification and how to test/debug on PC/mobile.

Blogs

Would you mind editing and re-posting your code as (formatted) text instead of images? This would make it searchable and infinitely easier to use. Thanks.

Hi,  Congrats for this post but im still waiting part 2.