Try using any app/website while you’re offline or have poor signal and you’ll more than likely receive a limited experience on apps, or no response at all on websites. We wanted to tackle this where it matters most, on your commute. Whether you’re on a train, tube or spaceship, The Commute website will deliver you an offline first experience.
By building an experimental progressive web application, powered by service workers, we were able to create a website that performs as good offline as it does online. Although this is currently only available on Android, IOS devices will still see improved performance however they’ll need a connection of some sort… for now anyway — IOS development status.
The idea: deliver content the user wants, curated to their commute time. A user selects the topics they’re interested in and their commute time so we can deliver a daily digest that meets their needs. We’ll give users an option to refresh the data once a day when they’re online, at all other times the content is loaded from local storage and assets (CSS, JS, HTML) are loaded from a service worker. As I mentioned before this is where IOS needs to hop online to download the assets.
T E C H N O L O G Y
Firstly, the term progressive web app spans an array of checkboxes your website should hit to be given the true status. For us we wanted to test a few key aspects:
- Network independent — it works offline and on a low quality connection.
- App like — it looks and feels like a native mobile application.
- Engage Users — through push notifications.
- Installable — users can add it to their home screen for easy app like access.
- Application Shell — the core aspects of the app are always present and stored by the browser meaning you’re never left with a white page.
These features should result in enhanced user experience making it feel fast, reliable and engaging.
- Vuex — state management system.
- Vue Router — to handle, umm routing.
- Vue Lottie — to render slick After Effect animations as SVGs.
- Velocity — to animate DOM elements.
- Vue Touch — a Hammer.js wrapper for touch gestures.
- Vuex-persistedstate — allowing us to optionally save/read state from local storage.
S T R U C T U R E
As with all our projects, the structure was heavily influenced by Atomic Design. Where code is split into: pages, templates, organisms, molecules and atoms.
We’ve broken this app into three pages:
- Settings — Where the user can change their commute time and news sections. Three templates: SetNews, SetTime and Welcome (for first time users).
- SelectDigest — Called when we want to update the news feed. Two templates: Loading and Ready.
- Digest — Displays the news feed and the article. Two Templates: ArticleTemp and NewsFeed.
A template is a navigational child of the page and therefore can be accessed with a url like: settings/time. Everything below a template is build up in a normal component structure, with properties and access to Vuex if needed.
Vuex holds the application state, like the time of the users commute. The store is built up of two modules:
- Settings — commuteTime, avaliableSections and section.
- Home — newsFeedStatus (request status), newsFeed, visitedArticles, lastUpdated, digestExpired, modalShown and scrollHeight.
vuex-persistedstate is used to keep some of this data available through multiple sessions by saving it to local storage and restoring the state when you come back to the application.
The data stored here would normally be associated with a user account and fetched on application load. Then to make it available offline a service worker would step in and return a cached API response.
Components can access specific items from the store through mapping and ones that need to make modifications have the corresponding action mapped.
The vue-pwa boilerplate comes with sw-precache-webpack-plugin already set up which is great and does most of the work for you. We did experiment with switching this to Google Workbox, however nothing could beat the precache simplicity.
Currently we store the returned newsFeed in Vuex and persist it with local storage. The next step for our service worker is to return an offline response for our API however this will need us to change the way we manage the timings of refreshing data.
O V E R V I E W
🎉 Successes 🎉
- A site that works offline on supported devices.
- Extremely fast loading, normally around 1 second.
- App like feel, with touch gestures and add to home screen.
- Slick animations with Lottie.
- Continuous integration & deployment with Docker, Jenkins and AWS.
😡 Fails 😡
- Offline data management could be improved with further service worker integration.
- Nesting child routes caused a pain when animating between them. Such as restoring scroll height. Would love to hear if you know a better way.
- No atoms created. It’s a pretty small app with few duplicated items.
- With time I’d like to add some more unit tests.
- User registration for better data management.
- The above would also allow us to learn user behaviour and improve your news feed making sure you only receive content you’re interested in.
- Push notifications when your new digest is ready.
- User option to allow the digest to be automatically updated in the background.
F U T U R E
We had two goals for this project, firstly to test out the idea of delivering curated content to readers for their commute, which is still underway, and secondly to experiment with progressive web applications and understand how they’ll impact web and mobile apps as we know them today.
This project has started touching on the future of web and native mobile app development showcasing just how close the two will become in the future. Where ‘simple’ mobile sites and native apps will merge into one, allowing for consistent design and one codebase. And before you start shouting about performance, maybe Web Assembly could lend a hand. Of course, we’re still waiting to see how Apple will integrate some of the key technologies needed to make this a reality.
One day platforms (mac, windows, android and IOS) could be asking developers to submit progressive web apps to app stores. Where the user will know no different from native and web.
Could this be the future?