What’s new on iOS 12.2 for Progressive Web Apps - 图3

Maximiliano Firtman

image.png
One year after the first initial support for PWAs on iOS, Apple released iOS 12.2 for iPhone and iPads with what it seems to be the biggest step forward in the last year, addressing the two most annoying problems we’ve been dealing with PWAs: reload effect and OAuth logins.
However, as expected, the release is not free of bugs or problems, but at least several problems I’ve reported from the first beta seems solved.

In a nutshell

I will get deeper on most topics, but if you don’t have time to read:

  • 💾 PWAs have a new lifecycle and on most normal situations, the state of your app will be saved and restored between sessions, but there is no way to kill the PWA and restart it from scratch
  • 🔁 A link to an external site opens in a “PWA In-App browser” instead of Safari and if the external site links to the PWA’s scope again, the navigation goes back to the PWA. Now we can log in users on external origins within a PWA (such as with OAuth).
  • 🔙 We have navigation gestures to go back and forward using “swipe from edges” within PWAs and the In-App Browser.
  • ⚠️ ️️The new In-App Browser means there is no way to call Safari from a PWA
  • 🤝 Web Share is supported (over HTTPS only)
  • ⚠️ Motion Sensors events are disabled by default and there is no API yet to request access to them
  • 🚨 HTTP websites will be marked as “Not Secure” in the URL bar
  • ⚠️ Old getUserMedia API was removed in favor of WebRTC, so if you are using the camera in Safari you might want to update your code.
  • 😳 PWAs in standalone mode are not inspectable anymore with desktop Safari (the Web App process doesn’t appear as inspectable)
  • 👍 IntersectionObserver, Conic Gradients CSS, , , Abortable Fetchs and inputmode attribute are now available
  • 👎 Same bugs and disabled features as in previous versions: no access to Camera within a standalone PWA, no full support of Web App Manifest, no installation API, ghost windows, and no default launch image.

image.png
“Not secure”: the new flag when you browse HTTP websites

The new Lifecycle

One of the worst issues for PWAs on iOS until now -if not the worst- is the reload problem. Every time you get out of a PWA, the instance is terminated, so if you go back to it, it restarts from scratch. That was making many PWAs unusable on iPhones and iPads, such as Starbucks, Uber and even Twitter in some situations, such as when using two-factor authentication.
Apple seemed to take note of the issue and in this release: there is a new lifecycle. While it’s not completely clear how it works, based on a couple of hours of testing this is my conclusion.
image.png

New PWA Lifecycle on iOS 12.2 according to my testing. focus, blur and visibility events only happen when loaded over HTTPS.

Detecting state change

While iOS is not supporting yet the new Page Lifecycle API (that will be really useful here), we can take advantage of the Page Visibility events: focus, blur, _and _visibilitychange. You can do that, for example, to store the app’s state in local storage to retrieve it later in the case of a full reload.
IMPORTANT: Events are only fired if the page is loaded through HTTPS. For some reason, they are not fired on HTTP.

When does the Web context run?

Your PWA will be executed if it’s in the foreground with no PWA Browser actually running. If the app is minimized (home screen button or gesture, or opening other app), you will have approximately 5 seconds in the background to execute code and, after that, your app is frozen.
When your PWA opens an external site with the new In-App Browser with target=_blank, you have approximately 2 seconds in the background before frozen. Then your web page context might resume when the browser is closed if the page is not reloaded.

The process

  • When you get out of a PWA, the “Web.app” or the mirror universe counterpart “WebApp1.app” processes are terminated immediately, but the web context is frozen and saved somewhere (that is, your JavaScript context, browsing context, scroll position, zoom state, form data). No more JavaScript execution after that happens; also no video will play in the background; audio is playing fine in the background.
  • Every PWA icon (a WebClip Bundle) has its own saved context, so two icons from the same PWA won’t share their context (but they share storage). If you open one and immediately another one, the first one will use Web and the second one WebApp1.
  • If you close the screen of your PWA from the multitask mode (killing it), it doesn’t delete the saved state! So if you open the PWA again from the icon, it will continue as its previous state. That means there is no way to reload the app or start it from scratch from the beginning from a user action.
  • If you go back to the app using multitask, a gesture or tapping on the home screen’s icon again, the PWA engine process starts from scratch but quickly restores your PWA state if available. So it’s not completely available as soon you go back as a native, but it’s much faster than starting it from scratch. On an iPhone X, there is approximately a one-second context load delay (white screen or launch image) when you go back to the PWA.
  • After some undefined time, the saved context seems to disappear. So if you get out of the PWA, do nothing with your phone and wait some hours to go back to the PWA, it restarts from scratch.
  • While the Web and Web1 processes seem to disappear from memory when you get out of the app, the saved context is shared with the rest of the OS memory. That means, if you get out of the PWA and you open a high-memory consuming native app, the saved contexts for all the PWAs might disappear and when you go back to the PWA, even after 20 seconds, your PWA might start from scratch as in iOS 12.1, as with native apps.
  • When you got out of the app, the OS still shows the launch image instead of a screenshot of the last moment you used the app. And if you don’t provide a launch image -as most PWAs unfortunately- you just see a white screen.

    PWA Browser

    Up to iOS 12.1, every link pointing to a destination outside of the manifest’s scope opens in Safari by default. From iOS 12.2, an In-App PWA Browser is used. Therefore, all your links now open within your own app’s scope and they may have a “Done” button to go back to your app.
    Every navigation that you make on that browser will happen there. Back gesture is enabled (dragging from the edge to the right) and if you are in the top level of that browser, it goes back to your PWA’s window.
    image.png

At the left, what happens today in iOS 12.1, the external URL opens in Safari with a small “back” button to your PWA in the status bar. At the right, two images on how it works on iOS 12.2. The URL opens in an In-App browser within the visual scope of your PWA

Sharing data with Safari

Websites loaded in this browser are not sharing storage or service workers with Safari. They share it with other instances of PWA Browsers though. So, if you are logged in on Facebook within Safari, you won’t be logged in on a PWA using OAuth.
image.png

The Done button to return to the PWA only appears when you load another page after initial external site load.

Detecting PWA Browser

If you have a website and you want to know if it’s being loaded in a PWA In-App Browser, you can use today: navigator.standalone or the display-mode: standalone media query.
While it seems good, it’s actually bad news. Let’s say you don’t have a PWA. That means, you never expect your display mode to be standalone. Well, now it will be exposed in that mode when it’s loaded from a PWA. Weird.
HTTP Headers including User Agent are the same as in Safari.

Going back to your app

When the external URL redirects or points to a URL within the scope -including POST requests, JavaScript redirects or links-, the PWA closes the browser and loads the content in the standalone window, coming back to the original PWA. This is particularly useful for OAuth authentication. The In-App browser shares storage context with the opener PWA, so you can use URLs outside of the scope but within the same origin to share data as well.
Something similar happens when you press the “Done” button (if it exists) or if you navigate back with the gesture. The PWA Browser closes and you return to the PWA.

Playing with the PWA lifecycle

Opening external links with or without target=_blank make a difference as in:

  • Without target=_blank, the PWA context is deleted, so when the browser closes, the page reloads in the standalone window
  • With target=_blank, the PWA context is restored when the browser closes

    Opening links using Safari is impossible

    I couldn’t find a way to let a PWA open a link in Safari though. I’ve tried everything I had in my recipe list: playing with target, with rel, with JavaScript, using Custom URIs. Nothing works; every link will open in your own app.
    You can only point to Chrome or Firefox (if the user have them) using the googlechrome(s):// or firefox:// URI schemes.
    image.png

If you install the appsco.pe PWA you can launch suggested PWAs within its boundaries but you can’t install them or transfer the navigation to Safari
For example, we can see a problem with this impossibility on PWAs such as AppScope, where you can launch other PWAs. While you can run them in the InApp Browser, there is no way you can add them to the home screen or switch into Safari to do that.

The PWA Browser is nice but…

While I think this solution is a step forward, there are some issues to solve:

  • There should be a way to request Safari for some cases (maybe with an specific rel or target attribute)
  • The Done button doesn’t appear at the first glance, so the user will be confused about how to cancel the popup browser (the back gesture is obscure)
  • No UI customization, such as using the theme-color
  • No way to see the full URL, only the domain
  • No visual way to navigate: back button, reload, etc.
  • No way to check TLS/SSL certificate to avoid phishing attacks
  • No way to move the navigation to Safari (as in Safari View Controller -the one used by the native Twitter app)
  • No way to share the URL from the browser
  • Standalone media queries and JS standalone attribute are exposed as true when it doesn’t seem the case

    Motion Sensors Disabled

    Because of some privacy issues, Safari has decided to disable Motion Sensors (accelerometer and gyroscope) access by default without an alternative API. This is used right now by AR, VR and 360 web apps to render content as well as games and other use cases.
    image.png

The only solution right now is to show a message to the user to go to Settings and enable the feature until some of the events are fired once (such as deviceorientation).
There is an API coming to request permission per site, but the WebKit team didn’t have time to get it done for this release. Chris Dumez from Apple confirmed that.

Navigation Gestures

image.png

Back gesture in action in a standalone PWA
Progressive Web Apps now have the navigation gestures enabled, similar to Safari. It works for every URL within your scope, including client-side routes and it’s mostly useful for the back action as there is no back button on the screen while in standalone mode. It also works when the new In App Browser is used (for navigation within external URLs and to go back to the internal window if you are at the top level).

Other changes

Web Share

Web Share Level 1 is now supported on all the Web platforms, including Safari, standalone PWA, WebView (such as Facebook Mobile Browser or Chrome on iOS) and Safari View Controller (such as a link opened within the Twitter native app). Only the text and URL attributes are working; the title is ignored.
image.png

Web Share works only after a user gesture and lets you share a link with a text on any native app, including native behaviors such as AirDrop or Copy.

Form additions

The first addition is the new color picker using the same space as the keyboard
image.png

With we can render a color picker. There is a bug here: on landscape mode the last row of colors is unselectable
The second addition is support for that looks very similar to a ,