Brewfather - Progressive App Review

In my spare time I enjoy a little bit of homebrewing. What first started out as an experiment with a beer kit, soon turned into a geeky fascination with the science behind brewing beer. I am one of those annoying people that sniffs the beer and comments on the aroma before tasting it! Like many hobbies out there, you can bet yourself that a piece of software exists to match the hobby. This couldn’t be truer for homebrewing.

When I first started exploring this hobby, there were many desktop apps and mobile phone apps, but they all felt pretty clunky and I could only see my data if I was logged onto a specific device. It seemed as if the default implementation was always desktop apps. After a bit of searching around I discovered a web app called Brewfather. Pleased with the easy to use interface, and as a web developer, I naturally started exploring under the hood and noticed that this was a fully fledged Progressive Web App. As it turns out, an application like this is perfect for the web and it’s also really good to see developers using Progressive Web Apps for commercial, real world examples.

In this article, I wanted to dig under the hood and take a closer look at how a great PWA like this is built and being used in the wild. (It’s worth mentioning that I am in no way affiliated with Brewfather - it’s just a cool web app!)

What is Brewfather?

Before I go any further, many of you may not be familiar with Brewfather (and nor should you be to read this article!), and it is worth explaining a little more. Brewfather allows you to easily create and manage your homebrewing recipes as well as keep track of all the details in your batches and your ingredients inventory. It’s got some great little built in calculators that help you determine your beer style, sugar content and bitterness levels to name a few.

Brewfather - Progressive Web App

If this was just built as a simple web app with no PWA functionality, it would be a great web app! However, by adding PWA functionality, the Brewfather team have managed to take it a step further. Brewfather has been written as a Single Page App (SPA) using Ionic v3 and uses a service worker under the hood to cache any assets that the user will need again. This means that it works completely offline - allowing homebrewers to access to their recipes and brewing details wherever they are, regardless of network connection. This definitely allows this app to shine and takes it to the next level!

Looking under the hood

Before we go any further, let’s take a deeper look under the hood. In order to find out a little bit more about Brewfather, I opened up Google Chrome and used the Developer tools.

With Chrome Developer tools open, if you head over to the Application tab, you can see that the web app has a Web App Manifest file, icons, a start URL and theme colours.

PWA - Chrome Application Tab

If we navigate to the Service Workers tab, you should see something a little like the image below. You’ll notice that a service worker has been installed and is controlling the page.

Brewfather Service Worker

Workbox & precaching

With a little bit of digging under the hood, I noticed that Brewfather is using Workbox.js. If you’ve not heard of Workbox before, it is a set of libraries that make it easy to cache assets and take full advantage of features used to build Progressive Web Apps. Think of it as a set of JavaScript libraries for adding offline support to web apps.

One feature of service workers is the ability to save a set of files to the cache when the service worker is installing. This is often referred to as "precaching", since you are caching content ahead of the service worker being used.

The main reasons for doing this is that it gives developers control over the cache, meaning they can determine when and how long a file is cached as well as serve it to the browser without going to the network, meaning it can be used to create web apps that work offline.

Workbox takes a lot of the heavy lifting out of precaching by simplifying the API and ensuring assets are downloaded efficiently.

You can see this in action on the Brewfather serviceworker.js file.

self.workbox.precaching.precacheAndRoute([
  {
    "url": "assets/font/_flaticon.scss",
    "revision": "fa8ccf9cd4c3ed4b4122abd45ffef487"
  },
  {
    "url": "assets/font/AngelineVintage.woff",
    "revision": "c2f686c43322502df1c28c5105b64f06"
  },
  {
    "url": "assets/font/flaticon.css",
    "revision": "8a0da5d051f6ab11e5701c7b1651ad5c"
  },
  {
    "url": "assets/font/Flaticon.woff",
    "revision": "7bc7d85cf32f8cf612ec6656d77fe1a0"
  },
  {
    "url": "assets/fonts/ionicons.scss",
    "revision": "c1fdfabf9cbd412b444f064d27641f10"
  }
]);

In the code snippet above, you can see that each file has a revision hash associated to it. Using the Workbox CLI tool, it will generate a unique hash for each file. If any changes are made to these files, the next time the CLI is run, it will update the hash, thus invalidating the cache for that file. The change to the service worker file will also mean that the browser picks this change up too.

If you’d like to learn more about this, I recommend heading over the to the Workbox documentation. I’ve also previously written about Workbox and how you can get any web app up and running with this great library.

Firebase

As I was browsing through the Brewfather web app, I noticed that when I was offline, I was still able to make change to recipes and batches even when I navigated away. After a little digging under the hood, it turns out that if you makes changes and save on the site, you’ll also notice that the network requests make requests to Firestore which is a flexible, scalable NoSQL cloud database to store and sync data for client and server-side development. The great thing about Firebase and Firestore is that it is a realtime database that takes care of the online/offline data syncing.

Firebase - Progressive Web App

If you’d like to learn more, I’ve previously written about Firebase on this blog. I do have to admit that my article is a little out of date and their API has been updated since this was last published.

Offline Support

The great thing about Progressive Web Apps is that they allow your users to access their content regardless of network connection. While this is great for static content, it can be a bit tricky when the user wants to save changes when they are offline. As a web developer, you currently have the ability to using Background Sync which allows you to defer actions until the user has stable connectivity. The thing is, it’s great for simple actions, but it can be a bit tricky when you need total control across a complex web application. This is where Cloud Firestore comes in.

It supports offline data persistence and it caches a copy of the Cloud Firestore data that your app is actively using, so your app can access the data when the device is offline. You can write, read, and query the cached data. When the device comes back online, Firestore synchronizes any local changes made by your app to the data stored remotely in Cloud Firestore.

Let’s turn our focus back to the Brewfather app. If you look a little closer under the hood using Chrome Developer tools, you can see that Firestore uses IndexedDb to save this information locally and then update the server when the user comes online again.

Firestore IndexedDb

If you’d like to learn how to build a web app using these great offline features of Firestore, I recommend reading the following article.

Summary

All in all, Brewfather is a great example of a Progressive Web App. It’s easy to access, it works offline, is super fast, and lets you access your data on the go. What more could you ask of a web application!

A big thank you to Thomas Gangsøy for letting me review his PWA and for building such a great web app.