Progressive Web Apps (PWA) Back
As an architecture to design web apps to make them more progressive, there is a series of mechanisms like service workers,
manifests you can use to do such an enhancement.
What has advantages brought by this architecture? It can conclude in different dimensions:
- Discoverable (can be found through search engines)
- Installable (can be launched via home screen or app)
- Linkable (can be shared via URL)
- Network independent (can work offline or with a poor network connection)
- Progressively enhanced (usable on a basic level on older browsers, but fully functional on the latest one)
- Re-engageable (can receive notifications in real-time)
- Responsively designed (usable in any devices with different resolution ratios)
- Secure (can protect sensitive data)
This document mainly focused on what we can do in these dimensions.
To enable web apps a better representation in search engines (a better SEO), we can:
- use some proprietary (所有權) technologies like Open Graph to specify metadata according to a specific protocol.
- define a manifest file to describe the name, author, icon(s), version, or other resources.
Installation of web apps is a feature available in modern browsers. It allows users to install apps on their devices or add them to the home screen on mobile devices. For example, if we define such a manifest file, Chrome will show an installation icon within the address bar, where users can install it.
{
"background_color": "purple",
"description": "Shows random fox pictures. Hey, at least it isn't cats.",
"display": "fullscreen",
"icons": [
{
"src": "icon/fox-icon.png",
"sizes": "192x192",
"type": "image/png"
}
],
"name": "Awesome fox pictures",
"short_name": "Foxes",
"start_url": "/pwa-examples/a2hs/index.html"
}
Besides, we can also prompt users to install inside the app:
let deferredPrompt;
window.addEventListener('beforeinstallprompt', e => {
// Prevent Chrome 67 and earlier from automatically showing the prompt
e.preventDefault();
// Stash the event so it can be triggered later.
deferredPrompt = e;
// Update UI to notify the user they can add to home screen
const addBtn = document.createElement('<span>');
addBtn.innerText = 'Add to home screen';
document.body.appendChild(addBtn);
addBtn.addEventListener('click', () => {
// hide our user interface that shows our A2HS button
addBtn.style.display = 'none';
// Show the prompt
deferredPrompt.prompt();
// Wait for the user to respond to the prompt
deferredPrompt.userChoice.then(choiceResult => {
if (choiceResult.outcome === 'accepted') {
console.log('User accepted the A2HS prompt');
} else {
console.log('User dismissed the A2HS prompt');
addBtn.style.display = 'block';
}
deferredPrompt = null;
});
});
});
All web apps should be linkable without an app store or a complex installation process.
There are some factors to detect whether an app is network independent. They can be:
- revisited even if no network is available.
- browsed any content visited at least once, even under poor connectivity.
- controlled what to shown when there is no connectivity.
To implement those features, we can:
- use Service Workers to control page offline requests, like querying data from a local cache.
- use Cache API for storing request / response objects.
- use Web Storage and IndexedDB to store application data offline.
The word "progressive" means that the design achieves a usable experience for users of older browsers and devices with limited capabilities, while at the same time having a fully-feature experience when the environment is capable.
To do so, we can use feature detection to determine different behaviours, and choose some polyfills tools like core-js
, autoprefixer
to add missing features.
The philosophy is similar with Graceful Degradation (平稳退化), but they are not the same thing, and progressive enhancement is more positive.
It means users can be re-engaged by updates and new content, even when not looking at the app or using their devices. For example, a new incoming mail can automatically update the mail list, rather than needing users to refresh manually.
There are some related techniques we may need to know:
- use WebSocket or Push API to construct connections between servers and clients to subscribe changes.
- use Notifications API to control the display of system notifications to the end-user in Web Workers.
We can use media queries and viewport to fit any device with different resolution ratio. It should be a big topic, and here is a suggested list of documents around this:
In addition to taking advantage of HTTPS, we can also use some methods to avoid XSS in web apps, like using js-xss, iframe sandbox, or Content-Security-Policy (CSP) Header to control resources.
Besides, it is a common case to escape HTML strings before rendering, when they are passed outside the app.