On March 30, the long-awaited iOS 11.3 update was released, with support for basic PWA features on iPhones and iPads, such as service workers and app manifest files. Although it is great that these are finally supported, the user experience of Progressive Web Applications on iOS is still not perfect.
That means that many existing PWAs still have some serious issues on Apple devices, while providing a near-native experience on Android at the same time. In the frontend community comments of disappointment were already raised, and the list of issues and bugs is long. Don't lose your hope, though! Below you will find a few tips on how to fix these issues and make your PWA as close to a regular mobile app as you can.
In the latest iOS update, Apple added support for service workers and app manifest files. You can now leverage caching with service workers and make your PWA work without an internet connection. Let's remember – this is a basic requirement within the PWA definition. And, unfortunately, there are a few drawbacks to Apple's implementation.
The support of service workers is very limited compared to Android. You can only persist app data and cache files, but no background tasks. There is also a 50MB and “few weeks” limit for storage.
iOS 11.3 also introduced support for manifest files. But our tests showed that it is far from perfect. Icons are not working perfectly (or at all) and there’s no support for launch screens - you’ll get only a blank white screen when the app is loading. The app is reloaded each time it is brought back from the background, and there's no support for push notifications and many other functionalities which are essential for a mobile app. To sum up - the overall UX is quite bad.
Thankfully, there's a lot you can do to improve your app's look and provide a better UX. With a few simple tricks you can build an app which, in a lot of cases, will be indistinguishable from a native one.
I believe that PWAs are the future of an inclusive, performative and intuitive web, which is why I would like to share some tips on overcoming iOS's limitations in terms of PWAs.
We've noticed that iOS does not use the icons from the manifest file, and that makes the shortcut to your app on the home screen look really bad. There is a simple solution to overcome this issue - just add an apple-touch-icon meta tag with the proper image. Avoid icons with transparency - those will not work.
And now your app will look perfect from the beginning!
A launch screen is normally displayed before an app is fully loaded and ready to use. Unfortunately, iOS doesn't support launch screens generated from the manifest, which is how it works on Android. Instead, it shows a white, blank screen That's definitely not the experience we would like to serve to our users.
Thankfully we've found the solution which is described in apple developer's page. Apple supports custom meta tags to specify a pre-generated splash screen - apple-touch-startup-image. So you just have to generate splash images in the proper sizes, which you can find listed below:
When you have your stunning launch screens ready, the only thing left to do is to link them in the head section like this:
Now you can see that ugly white screen on launch is gone:
Our PWA is looking much better thanks to that, isn't it?
On Android, there is a native popup which encourages the user to add an app to their home screen and informs them that our page is a PWA. Unfortunately, there's no such thing on iPhone, so our visitor is not even aware of our app's capabilities. Moreover, as much as 3 taps are required on iOS to add an app to the home screen.
But don't worry, we have a fix for that! We can add a custom popup which will indicate that our app can be added to home screen.
You are free to design that popup as you wish, our example is shown below. The hard part is to display it only in Safari and not in standalone mode (when the app is already added to home screen). You can check if your app is in standalone mode using window.navigator.standalone.
Take a look at this snippet:
After creating the proper popup component and pasting the detection code into the proper lifecycle method, the final product will look like this:
Just bear in mind that on iPad the share button is located at the top of the screen, next to the address bar, so you should change the popup's location accordingly.
Since iOS restarts your app on every launch/going to background, you should take care of persisting its state yourself. If you use React and Redux, there are some great packages to help - redux-persist and react-router-redux. For Vue, you could use the similar vuex-persist and vuex-router-sync. Of course, you can create your own solution, which would be the best fit for your case.
In React, react-router-redux will by default redirect on mount to the route specified in the URL. While it might be OK for regular use, we would like to prefer the route which was persisted in our storage. This is an example of how to achieve that:
To make sure your app will be usable in standalone mode, you have to check if you have implemented your navigation correctly. On Apple devices there's no back button, so you have to make sure that user is able to go back from any screen using navigation built-in to your app.
You can do that by displaying a back button or by adding an additional menu bar for iOS devices.
To provide the true native experience you should be prepared for weak or no connection at all. In some simple cases, persisting store data will be enough, but this is where we can leverage our brand new (on iOS) Service Workers API - we are able to cache network requests (eg. API calls) there.
To take advantage of caching with service workers, you could use the example code provided by Google. Make sure that you've read the linked article to be aware of the pros and cons of that template.
After setting the proper paths to the assets which you'd like to cache and registering a service worker, you should be good to go (offline). It's also good to indicate that the app is offline - you can add online/offline events listeners to display a notification.
That's how the final result looks in our example app:
These tips will help you provide a near-native UX for your PWA on iOS. But, of course, there are still some issues that could be solved. We still don't have support for:
Also, you should keep in mind that caches and any locally-stored data are not shared between Safari, WebView, and Web.App. This means that he user will have to, for example, log in again after adding your app to the home screen, which could cause bad UX in some cases.
Have an idea? Share it with us!