Maxim Salnikov
@webmaxru
Native Web Apps:
Are We There Yet?
How do we want web apps to feel like
and what tools do we have to achieve it
Maxim Salnikov
-
PWA Summit co-organizer
-
PWA Oslo / PWA London meetups organizer
-
Google Dev Expert in Web Tech / Capabilities & Installability
Developer Audience Lead at Microsoft
1989
A “web” of “hypertext documents” could be viewed by “browsers”
2023
-
Historically depends on the "connection status"
-
Works within the browser context, not underlying platform
-
Evergreen browsers
-
Excellent tooling
-
Huge community
Web Almanac 2022
Requirements
-
Security & privacy
-
Performance
-
Persistence
-
Nativeness
Native-like...
-
Installation, configuration, launch
-
Windowing
-
Outbound integrations
-
Inbound integrations
-
Notifications
-
Background tasks
-
Access to hardware
Demo app
- Link to GitHub repo with source code
- Many extra and extended features
- How to host in the cloud for free
edge://flags
We want to install, uninstall, configure app and launch it in different ways
-
Installation prompts
-
App hubs
-
Metadata update dialogues
Installation
Launch
-
Run on user login
-
Shortcuts
-
Launch mode
Installation criteria
Web App Manifest
Service Worker with "fetch"
{
{
"name": "BPM Techno",
"short_name": "BPM Techno Counter",
"start_url": "?utm_source=homescreen",
"display": "standalone",
"background_color": "#fff",
"description": "A free online BPM counter",
"icons": [{
"src": "images/touch/48x48.png",
"sizes": "48x48",
"type": "image/png"
}]
}
app.webmanifest
Shortcuts
"shortcuts": [
{
"name": "Upload MP3 File",
"short_name": "Upload MP3r",
"description": "Count BPM of the uploaded file",
"url": "/upload-mp3?utm_source=homescreen",
"icons": [{ "src": "/icon-mp3.png", "sizes": "192x192" }]
}
]
app.webmanifest
Launch mode
"launch_handler": {
"client_mode": "auto" | "navigate-new" | "navigate-existing" | "focus-existing"
}
app.webmanifest
launchQueue.setConsumer(launchParams => {
const url = launchParams.targetURL;
});
main.js
We want to follow UX principles of the platform and have control over every pixel
Windowing
-
Main window mode
-
Title bar options
-
Tabbed experience
{
"display": "fullscreen" | "standalone" |
"minimal-ui" | "browser",
"display_override": ["window-control-overlay",
"minimal-ui"],
}
app.webmanifest
Windowing
-
Main window mode
-
Title bar options
-
Tabbed experience
titlebar-area-x
titlebar-area-y
titlebar-area-width
titlebar-area-height
CSS Variables
navigator.windowControlsOverlay.
getBoundingClientRect()
navigator.windowControlsOverlay.visible
JavaScript API
Windowing
-
Main window mode
-
Title bar options
-
Tabbed experience
{
"display_override": "tabbed"
}
app.webmanifest
We want to use all available interfaces of the platform
Outbound integrations
-
Web Share API
-
Contact Picker API
-
File Access API
if (navigator.share) {
navigator.share({
title: 'BPM Techno',
text: 'Check out BPMTech.no',
url: 'https://bpmtech.no',
})
.then(() => console.log('Successful share'))
.catch((err) => console.error(err));
}
main.js
Outbound integrations
-
Web Share API
-
Contact Picker API
-
File Access API
const props = ['name', 'email', 'tel'];
const opts = {multiple: true};
try {
const contacts =
await navigator.contacts.select(props, opts);
handleResults(contacts);
} catch (err) {
console.error(err));
}
main.js
Outbound integrations
-
Web Share API
-
Contact Picker API
-
File Access API
let openFileHandle;
btnOpen.addEventListener('click', async () => {
[openFileHandle] =
await window.showOpenFilePicker();
const file = await fileHandle.getFile();
const contents = await file.text();
});
main.js
const saveFileHandle =
await window.showSaveFilePicker();
const directoryHandle =
await window.showDirectoryPicker();
We want to platform to invoke the app in different ways
Inbound integrations
-
URL handlers
-
Declarative Link Capturing
-
Protocol handlers
-
File type handlers
-
Share target
"url_handlers": [
{
"origin": "https://bpmtech.no"
},
{
"origin": "https://partnerapp.com"
}
]
app.webmanifest
"web_apps": [
{
"manifest": "https://partnerapp.com/manifest.json",
"details": {
"paths": [
"/public/data/*"
]
}
}
]
.well-known/web-app-origin-association
Inbound integrations
-
URL handlers
-
Declarative Link Capturing
-
Protocol handlers
-
File type handlers
-
Share target
"capture_links":
"none" | "new-client" |
"existing-client-navigate"
app.webmanifest
Inbound integrations
-
URL handlers
-
Declarative Link Capturing
-
Protocol handlers
-
File type handlers
-
Share target
"protocol_handlers": [
{
"protocol": "web+bpm",
"url": "index.html?bpm=%s"
}
]
app.webmanifest
web+bpm://bpm=120
Inbound integrations
-
URL handlers
-
Declarative Link Capturing
-
Protocol handlers
-
File type handlers
-
Share target
"file_handlers": [
{
"action": "/open-mp3",
"accept": { "audio/mpeg": [".mp3"] },
"icons": [
{
"src": "./images/mp3-file.png",
"sizes": "144x144"
}
]
}
]
app.webmanifest
window.launchQueue.setConsumer(launchParams => {
const fileHandle = launchParams.files[0];
});
main.js
Inbound integrations
-
URL handlers
-
Declarative Link Capturing
-
Protocol handlers
-
File type handlers
-
Share target
"share_target": {
"action": "/share",
"method": "GET",
"params": {
"title": "title",
"text": "text",
"url": "url"
}
}
app.webmanifest
window.addEventListener('DOMContentLoaded', ()=> {
const parsedUrl = new URL(window.location);
const url = parsedUrl.searchParams.get('url');
});
main.js
We want to keep user always updated
Badging
navigator.setAppBadge(42).catch((err) => {
console.error(err)
});
navigator.clearAppBadge().catch((err) => {
console.error(err)
});
main.js
#30DaysOfPWA
Web Push
Is coming to iOS / iPadOS devices this year!
We want to run some parts of the app in the background
Background tasks
-
Background Sync
-
Periodic BG Sync
-
Background Fetch
-
Payment Handler
We want to have direct access to the hardware
Access to hardware
- Audio & Video Capture
- Geolocation
- Web Bluetooth
- Web MIDI API
- Magnetometer API
- Web NFC API
- Device Memory API
- Network Information API
- Battery Status API
- Ambient Light Sensor
- Proximity Sensor
- WebHID
- Serial API
- Web USB
- User Idle Detection
Where to follow?
🐡
How to experiment at scale?
Native Web: Are We There?
-
Installation, configuration, launch
-
Windowing
-
Outbound integrations
-
Inbound integrations
-
Notifications
-
Background tasks
-
Access to hardware
Thank you!
@webmaxru
Let's stay connected
Questions?
@webmaxru
Maxim Salnikov
Where to host your native web app?
...and visit Microsoft booth :)
Learn about web frontend, get prizes
Native Web Apps: Are We There Yet?
By Maxim Salnikov
Native Web Apps: Are We There Yet?
There are so many discussions about web VS native apps. Will we get to the point where the Web becomes truly Native for the majority of the platforms? Progressive Web Apps, Project Fugu, WebAssembly & other technologies actively contribute to moving in this direction. In this session, we go through a list of details that make the integration of an application & operating system seamless, and map it to the APIs available for the web platform. With the knowledge of what's available today and what's coming soon, you are empowered to build truly Native Web Apps to deliver the best user experience!
- 2,737