Close

Progressive web apps in Java

What is the big deal about Progressive Web Applications (PWAs) and why are they trending nowadays? Here is one explanation by Google:

“It [PWA] loads quickly, even on flaky networks, sends relevant push notifications, has an icon on the home screen, and loads as a top-level, full screen experience.”

The number of users accessing web applications from a mobile device is bigger than those using desktop. And it’s increasing. If you want your web app to reach a bigger audience, while increasing the usability and experience for your users, then PWA is basically your way to achieve that.

Java app, running on browser without PWA
Same app, running standalone with PWA

PWA sounds like a new framework, or a tool to create some sort of web apps. Many developers link it to JavaScript, and that is only achievable with one of those new framework.js out there.

I’ve been wondering about the truth of the previous statement: can we create a PWA in, let’s say, pure Java? I did some research and in this article, I’m going to present my findings.

  • For Vaadin developers:

    • This is a perfect summary for you, saving a lot of time and hassle. Follow the quick steps, and you get a PWA immediately.
  • For Java web developers:

    • This is still relevant for you. Many concepts are the same for any Java web app.

In the following Devoxx presentation, Vaadin Expert Teemu Suo-Anttila and myself showed how it’s possible to create a PWA with a Java UI framework such as Vaadin:

Extracting the content of that video here, but I’ll not use Spring this time, I’ll keep it as much generic as possible. Here are the steps summary:

  1. Dismantling a PWA. We will take a quick look at an existing PWA and compare it with a normal Java app, to understand the major differences and what needs to be implemented.

  2. Building a PWA.

    1. Add a service worker, It will help us implement modern browser functionalities, and other features that do not require a running web app, such as background sync, caching, and push notifications.

    2. Specify files to be cached, this makes the app load faster in future visits, and makes a part of it available offline.

    3. Update the service worker, what are the best practices to update the service worker when we add more functionalities to it?

  3. Making it app-like. And this part is magically done with the help of the browser, if we only include a standard manifest file.

1) Dismantling a PWA

To practically test that a web application follows PWA specs, there is a tool called lighthouse that generates a report showing how compatible you app is with the PWA specs.

Let’s start by looking at the state of a Java-based application today, by creating a very simple Vaadin application and then running the lighthouse report for it. Unfortunately, at this point I get 22% compatibility and the report shows a lot of missing features in this simple app.

Related commit: Step 0 | Simple Vaadin App

Reverse engineering an already existing PWA is my favorite way to understand how it works. Luckily there are many templates in the open source web that give some guidance on how to start. For example, if you follow the guide in this GitHub project generator-pwa, you will end up with a minimalistic web project that follows most of PWA specs. Lighthouse gives it a score of 88% and we can easily see that there are a couple of small problems, and since we are testing locally, it’s not secure over HTTPS and thus not a perfect score. But still good enough to start with, and let’s make it our benchmark for a PWA with Java.

Related commit: Step 1 | Simple JS PWA

2) Building a PWA

Now we have a working reference to copy from. Yes, I mentioned it right, I will copy the code. The idea here is, I’ll decrease the learning curve. Instead of reading many references telling what to implement, a service worker, full screen, manifest etc, I will just copy working code and build based on it.

At the bottom of the PWA template’s index.html, there is a reference to a Javascript file

And by opening app.js we find that it’s responsible for registering and communicating with the service worker. Here is the code responsible for registering the service worker sw.js

Let’s start by copying app.js into our Vaadin app. The best location to place it would be under webapp/VAADIN, so I create a new folder called js and place it there.

To link to app.js inside our Vaadin app, we can use the @JavaScript annotation on top of the main UI class:

Related commit: Step 2 | Add JS responsible for SW

2.1) Add a service worker

To give a correct scope for the service worker, it must be placed in the context-root of our Java application. That’s why I will copy sw.js to the resources folder, and update the reference in app.js

We don’t want the ‘/’ scope but the current context-path given by the application server is ‘java-pwa’ in my case here, or ‘./’ in general.

To be able to inject the service worker in the root of the application, we need to make some modifications in the default servlet to handle this specific request. Here is a code that handles ./sw.js request and serves the content of our sw.js file.

Related commit: Step 3 | Add service worker

2.2) Specify files to be cached

Inside sw.js we find a reference to the files to be cached:

I removed irrelevant files from the filesToCache list and update paths:

I kept the /images/touch/chrome-touch-icon-192x192.png to be cached, because it’s needed by the app shortcut icon. You can either copy the one provided in the template, or add your own.

The lighthouse score at this point is 34%, it seems there is some progress. At least we can see a detected service worker, and those cached files make the application actually work offline!

Related commit: Step 4 | Update cached files

2.3) Update the service worker

In our PWA template, the functionalities of the service worker were kept to minimum, to make it just work as a proof of concept. But how to update the service worker running on the client, once we add extra functionalities to it?

Just like any installed app, there is a life cycle in which, at some point you must kill the running app, and replace it with a new one.

The most interesting fact with the service worker is that, once its code is modified on the server, the browser will download the newer version and attempt to ‘install’ it. By default the new version will be on a ‘waiting’ state, till the currently opened page is closed. Google explains the process nicely, but there is more you can do!
So you open the web page, it downloads a new service worker, installs it, but still uses the older version? You can overcome this by ordering it to skip waiting. This would be done in our code as the following:

We will then have to claim the current active client as following:

Related commit: Step 9 | Skip waiting when updating the service worker

3) Make it app-like

The previous report shows that some tags are missing from the header of the app, such as meta theme-color, meta viewport, and more importantly the manifest.json file.

The manifest file is needed to install the app on the homescreen and it contains some information about the app, such as the name, description, icon for splash screen etc. We need to link to it in the <head> tag, so I will use the HeaderTags Add-on which will help me modify the bootstrap easily.

After installing the maven dependency, I can do something like this:

And include the manifest.json in webapp/VAADIN directory, after making some modifications to be relevant to our app. At least the start_url should be updated, as well as the icons list.

Related commit: Step 5 | Include manifest file

We can also include some other header tags, as pointed out in the report. At this point we have a score of 86%, which is a huge improvement from the original 22%.

Related commit: Step 6 | Add relevant meta tags

The score is not 88% yet, we can see a slight improvement once we turn on production mode, compress resources, and cache widgetset.

Related commit: Step 7 | Compression and production mode

Summary

Throughout this process, we have seen clearly that integrating PWA functionalities is not limited to JavaScript apps. The trickiest part was including the service worker in the context-root. For offline functionalities, currently it will show an empty page. It can be improved by either showing a fallback “no connection” screen, or using alternative components that work offline and do not rely on the server side.

There are some other small limitations like wrong tabindex, and no possibility to inject app.js at the bottom of the page instead of head. But the good news is, Vaadin Framework Team promised to make this way easier and much more straightforward in upcoming Vaadin releases (Vaadin 8.x maybe?). PWA is still a new concept, but our team is making sure to incorporate all new functionalities and make them part of the framework and ready to use once standardized.

Overall, next time you hear someone telling you that JavaScript is required for PWA, please show them this article! The service worker is an exception at the moment, so unless you will copy the one provided here as it is, currently adding extra functionalities to the service worker requires writing (or copying) some JS code into the sw.js file. I’m working on improving this to make it even easier, I’ve heard many suggestions from the R&D team and I’m exploring more ways to make the experience pure Java and with the least amount of steps possible.

Spoiler alert! Right now I’m working on getting web notifications to work, as well as a fallback screen when offline.

Do you have more ideas? Contributions?

What else would you like to see as part of the PWA specs in your app?

The GitHub project is waiting for your input, you can also place your ideas as comments below.

Here is the final app with some data, and working on mobile:

Related commit: Step 8 | Show data in a working app

Get the source code along with detailed steps!

You can also take a look at a similar concept done with Spring boot: https://github.com/tsuoanttila/sportstracker

Read the Free Web Platform Report 2017 Today

After months pouring over and analyzing the data, we are proud to announce the release of the Web Platform Report 2017. This report is the result of a collaboration between teams at Vaadin, Polymer, and Skate. Together we ran a survey in the fall of 2016 and received 851 responses from developers of all stripes.

  • Who uses web components?
  • How do developers write web apps?
  • What does the community think about progressive web apps?

Click on the banner to get a copy of the free report.

A Web Platform collaboration

Last year, the developer relations team for Vaadin Elements noticed that there was not much information available publically about the actual usage of Web Components and Progressive Web Apps in the real world. We decided to reach out to teams at Polymer and Skate, each of whom have built web components libraries and tools. Each of our teams is passionate about the future of web components and we wanted to build the conversation about web components.

Methodology

In autumn of 2016, our three groups collaborated on a set of questions that we thought would best cover the information we wanted to learn. We came up with 61 questions to cover everything from “what kind of developer are you”, and “who decides which technologies to use,” to “how would you change web components.” We balanced questions about developer practices with attitudes toward the web platform.

We then distributed the survey among web component creators and library authors and started collecting results. We added a message to webcomponents.org asking for responses. We also shared the survey link among stakeholders on Twitter and got a lot of visibility from being promoted at last year’s Polymer Summit. We were proud to collect 851 responses before the survey completed late in the fall.

Highlights

We’d like to share a few quick highlights from the report here. You can get a free copy of the report by following this link.

Click here to get a copy of the free report.

Simplifying Performance with Web Components

Why the solution to slow web apps isn’t a more complex set of tools

A while back I was working on an Angular app. What struck me was that Angular is not really only a framework, rather it’s an entire platform of its own built on top the Web platform. The reasoning behind this is to give developers a unified way of building apps across different platforms. But what’s the cost of using this abstraction?

For you, as a Web developer it means that for most things you know how to do on the Web, there’s a (slightly) different version of accomplishing that in Angular. It also means that you don’t have direct access to new web technologies as they come out, you need to wait for the Angular team to add support for them. ServiceWorker support is a good example.

Perhaps most importantly though, it means that there’s inevitably a layer of JavaScript running between your application code and the browser that is running the Angular platform. How does this impact performance?

Angular has put a lot of emphasis on performance in Angular 2 and subsequent releases. The performance builds a highly modular architecture, an Ahead-of-Time (AOT) compiler and pre-rendering. When writing the Angular app, though, I couldn’t help feeling like I could have built the same component-based application using Web Components and have it run directly in the browser. Surely, that would be faster?

Can we make things easier…and faster?

I got support for my idea at Chrome Dev Summit while listening to Alex Russell giving a strongly opinionated talk on Web app performance. He went as far as claiming that if you are using a framework, you are “failing by default” when it comes to performance. Frameworks are focusing on catering to developers, often at the cost of end users. The developer needs to consciously work (sometimes around the framework) to deliver a fast experience to their users. I caught up with Alex after his talk, and we had an interesting talk about how these problems get further worsened by real-life devices and networks.

At this point I was intrigued and wanted to see if I could, in fact, recreate the Angular with nothing but Polymer, and if that app would be faster than the optimized Angular application.

To keep things more focused, I split my findings into two posts. This first post will cover my initial question, can Web Components be used to build faster web experiences with less tooling? The second part will take a look at the actual developer experience of building an app with these two ways and how we could improve those.

Apps and oranges

Now some of you may be thinking that isn’t comparing Angular, a framework, with Polymer, a library, a bit like comparing apples and oranges. After all, one is meant for building applications while the other is only concerned with building components.

Well, as it turns out, the way you build apps out of component is by combining smaller components into more and more complex compositions until you end up with an app. So, to build a component-based app, all you need is a way to make components.

Both Angular and Polymer ship with their own set of tools to help developers. Most notably, both include a command line (CLI) tool that can be used to bootstrap new projects and build the app for deployment. Polymer also includes some framework-like features like support for routing.

My Test Setup

To compare the two approaches of building applications, I needed to build the same application with both. The application I developed is a mock portal application listing and showing stats for patients. It consists of three views: 1) a login view, 2) a listing view with master/detail editing, and 3) an analytics view showing chart data.

The Angular application uses Kendo Grid and Charts in addition to the core Angular framework. The Polymer app, in turn, uses Vaadin Grid and Charts. While the components are not identical, they are close enough in complexity and functionality to work for this comparison.

I built the applications following the instructions for production builds. For Angular 2, that meant using Ahead-of-Time (AOT) compilation and production mode in the build (ng build --aot --prod). For Polymer, I used polymer build to create a bundled build (concatenating dependencies into as few files as possible). Both apps used lazy loading of dependencies per view. The Polymer app build process additionally created a Service Worker that pre-loads subsequent views into cache while the user is logging in.

Both applications were served with Gzip enabled and communicated with the same REST API hosted on localhost. To get more realistic measurements, I used a simulated “Good 3G” connection with a “High-End Device” in Chrome Dev Tools.

I ran all tests with Chrome. I also ran a comparison test on webpagetest.org against versions deployed on GitHub pages.

How fast does this thing go?

There was a very clear winner in terms of initial load speed. The Polymer-based app was visually complete and ready to be interacted with in just 0.8 seconds. It took the Angular app a whopping 4 seconds longer to get done (4.8s). For the initial load, Polymer was 6x faster than Angular.

Why is this? Even with AOT compilation, Angular 2 has two distinct disadvantages compared to Polymer. First, since everything is in JavaScript, it needs to get downloaded, parsed, and evaluated before anything can be shown to the user. Polymer, on the other hand, can use the browser’s built-in streaming capabilities to show the app as it’s being downloaded. Second, Web Components are browser-native constructs. No matter how optimized the JS is that Angular outputs, some things are just faster to run directly on the browser itself.

For the initial load, Polymer was 6x faster than Angular.

For subsequent page loads, the difference is much less drastic. There are some differences, but I suspect those boil down mostly to the components used on those pages (charts and data grid) than to the technology used. The chart below summarizes the performance measurements for the entire app.

 


Interestingly, the app loads faster also when using Safari and the Web Components polyfill:

Both apps were roughly the same size in terms of download (Polymer: 630kB, Angular: 689kB) and lines of code (Polymer: 1999 lines, Angular: 1953 lines).

The full test can be found here.

So what about pre-rendering?

I could have used pre-rendering in the Angular app to improve the perceived speed. I say perceived because while pre-rendering lets the user see (a good estimation) of the finished page much faster, the added complexity can actually make it slower to get the page interactive. While the scripts are loading, the page looks complete, but nothing happens when a user tries to interact with the page.

There are other reasons, like SEO, why you might want to do pre-rendering, but as far as performance goes, I wanted to focus on how long it takes to get the app to a usable state.

It should be noted that Polymer does not support pre-rendering. Instead, the Polymer team is advocating for the use of the PRPL-pattern to achieve speeds comparable to pre-rendering without the added complexity of running the app both on the server and in the browser.

Conclusions

Web Components are fast. For the initial load, I was able to achieve a 6x speedup compared to the same app implemented in Angular. And I was able to achieve this speedup with a much simpler set of tooling — no AOT compilation, no pre-rendering.

But another question remains — can you build real, complex apps with only Web Components? It doesn’t do us much good that Web Components are fast if we’re not able to use them to build app. The strength of Frameworks is in the structure they offer to help developers build large, maintainable applications. This is something that Polymer or Web Components in general don’t offer.

In the second part of this article, I’ll dive into the developer experience of building these apps and what we might be able to do to make it easier for developers to build blazing fast web experiences.

 


The sources for both apps are up on GitHub:

Polymer app

Angular app