How to make an Elm app Progressive

cedd burge
codeburst
Published in
4 min readJun 25, 2018

--

Writing native mobile apps is harder and more expensive than writing web apps, so it’s best to avoid it when you can. Progressive web apps increase the number of situations in which a web app is suitable, and thus saves time and money. There are many other supporting technologies moving in this direction, such as Web Assembly, Web Bluetooth, and more.

Progressive web apps:

  • Can be “installed” on Android and Apple devices, and look like any other app. They have an icon and load full screen (without any of the browser UI)
  • Can cache content locally, to improve load time and so that they continue to work with intermittent (or no) internet connection
  • Can include push notifications (for “new email” notifications and suchlike)

If you use Create Elm App, your app will be progressive out of the box. If you have existing projects, or want a less opinionated solution then read on. In this tutorial, I start with a minimal Elm app, continue by making the manual changes required to make it progressive, and then finish by configuring Webpack to make the changes automagically. This tutorial assumes basic knowledge of Elm, Webpack, Node, Npm / Yarn and Chrome Dev Tools.

Initial Elm App

You can see the code for initial minimal Elm app at this commit in the companion repository, and browse it on netlify. To make the manual changes, I ran npm run build, which creates a deployment in the “dist” directory.

Making the app progressive manually

I then copy and paste this directory to “dist2”, and make manual changes to make it progressive. You can see all these changes at this commit, or use the links in the following sections.

ServiceWorker.js: This file registers the Service Worker, which adds event listeners to the browser in order to cache pages (diff).

Manifest.json: This file contains the settings for Android / Apple installation. It defines Application Name, icons, colours etc (diff).

Index.html: Some script is added to register the Service Worker on supporting browsers, and to link to the Manifest. All files within the App should link to the manifest, Android / Apple devices will open any that are not inside a browser, which is probably not the experience you want (diff)

Testing: You can npm install serve -g, and then serve within the “dist2” directory to host the app (or browse my deployment). Open it in Chrome and then look at the Service Workers on the Application tab of the DevTools. It should show that the service worker has been registered. To make sure that the cache is working, you can tick the “Offline” checkbox and reload. If it is working you will still be able to see the app. If not you will see the “There is no internet connection” page.

Making the app progressive automagically, via Webpack

Having made manual changes, I now know what my target state is, and I set about configuring web-pack until I get there. You can see all these changes at this commit, or use the links in following sections.

ServiceWorker.js: Firstly instally the plugin (npm i sw-precache-webpack-plugin), and then add the sw-precache-webpack-plugin to webpack-config.js. Set the cacheId to something that is unique to you (maybe a repository name) (diff)

Manifest.json: Firstly install the plugin (npm install webpack-pwa-manifest), and then add the webpack-pwa-manifest to webpack-config.js. Set the relevant details for your application (diff)

Index.html: The changes to index.html are still manual, and are the same as before. They are retained during npm run build so it’s a one time job (diff)

Testing: You can npm rum build to have have Webpack create a new deployment in the dist directory, and then serve it (or browse my deployment). You can use the Chrome Dev Tools as before to make sure everything is working.

Conclusion

Modifying an Elm App to be progressive is worthwhile and easy (now you know how!) In my opinion progressive web apps will become the dominant mobile paradigm in the near future and will reduce native mobile apps to niche use cases.

Further Reading

In order for a web app to be truly progressive (and be “installed” on Android / Apple devices), it must be served over https. I highly recommend Netlify for hosting your Elm apps (they have a tick box for https).

Once registered, Service workers stay registered in the browser, which can be confusing. The Chrome DevTools, “Application” tab has a section for Service Workers, where you can tick “Update on reload”, to make sure that changes are applied immediately. In this case it is still possible for an old service worker to be working, even when your current app has no service worker. If you encounter some weirdness, click on “Unregister” to make sure.

Push events are an extra level of complexity, Google have a good tutorial if you want to take it further.

Google also provide a tool called Lighthouse, which can test how well your app performs against the Progressive Web App checklist.

The solution presented here is simple and easy, and works well when starting out. When your Service Worker / caching requirements get more complicated, consider using Toolbox instead.

--

--