Webbläsarens API:er
En PWA ska vara installerbar, pålitlig och kapabel. De två första har du arbetat med i kursvecka 15 och 16. Den här artikeln handlar om den tredje: att webben kan göra sådant som tidigare krävde en installerad app, som att dela via operativsystemet, läsa platsen eller prata med en Bluetooth-enhet.
Ingen förväntar sig att du kan alla dessa API:er utantill. Poängen är att veta att de finns, och att kunna ta ett nytt API i bruk på ett sätt som håller. För högre betyg på B3 ska PWD:et eller någon underapplikation använda minst ett webbläsar-API du inte redan har använt i kursen. Listan nedan är ett bra ställe att börja leta.
Tidsåtgång: Ungefär 15 minuter.
Tre frågor till varje API
Section titled “Tre frågor till varje API”MDN har en lista över alla Web API:er, och den är lång. Innan du bygger på något av dem behöver du svar på tre frågor: finns det, får jag använda det, och vad händer annars?
På MDN:s sida för varje API finns en tabell över webbläsarstöd. Märkningen Baseline betyder att funktionen fungerar i alla de stora webbläsarna, och Limited availability att den inte gör det. Can I use ger samma information. Slå alltid upp det, för läget ändras.
Finns det? Feature detection
Section titled “Finns det? Feature detection”Testa om funktionen finns i stället för att gissa vilken webbläsare det är:
if ('share' in navigator) { shareButton.hidden = false}Ofta kan du erbjuda något enklare i stället. Web Share öppnar operativsystemets delningsmeny, men finns inte i alla webbläsare. Clipboard API finns i alla:
shareButton.addEventListener('click', async () => { const data = { title: 'Memory', url: location.href }
try { if ('share' in navigator) { await navigator.share(data) } else { await navigator.clipboard.writeText(data.url) status.textContent = 'Länken är kopierad.' } } catch (error) { if (error.name !== 'AbortError') { status.textContent = 'Det gick inte att dela.' } }})Det här är progressive enhancement: applikationen fungerar överallt, och blir bättre där det går.
AbortError betyder här att användaren stängde delningsmenyn, vilket inte är något fel.
Får jag? Secure context, aktivering och behörighet
Section titled “Får jag? Secure context, aktivering och behörighet”Webbläsaren ger inte vilken sida som helst tillgång till enheten. Det finns tre spärrar.
Secure context. De flesta nyare API:er finns bara på sidor som laddats över HTTPS. localhost
räknas också som säkert, så under utvecklingen märks inget. Det kan du kontrollera med
window.isSecureContext.
Användaraktivering. En del API:er kräver att användaren nyss har gjort något, till exempel klickat. Så hindras en sida från att öppna en delningsmeny eller gå till helskärm av sig själv. Aktiveringen varar bara en kort stund.
Behörighet. För känsliga uppgifter frågar webbläsaren användaren, och användaren kan säga nej:
locateButton.addEventListener('click', () => { navigator.geolocation.getCurrentPosition( (position) => showPosition(position.coords), (error) => { status.textContent = error.code === error.PERMISSION_DENIED ? 'Du har inte gett tillgång till din position.' : 'Det gick inte att hitta din position.' }, { timeout: 10000 } )})Fråga när användaren gör något som behöver svaret, inte när sidan laddas. En fråga utan sammanhang får
oftast ett nej, och ett nej är svårt att ändra. Användaren måste då själv gå in i webbläsarens
inställningar. Vill du veta läget i förväg, utan att fråga, finns navigator.permissions.query().
Fråga: på telefonen
Section titled “Fråga: på telefonen”Du testar PWD:et på din telefon. Du startar Vite med npm run dev -- --host och öppnar
http://192.168.1.20:5173 på telefonen. Delningsknappen ovan fungerar på datorn via localhost. Vad
händer på telefonen?
Knappen ger fel, trots att telefonens webbläsare har stöd för både delning och urklipp. Sidan laddas
över HTTP från en vanlig IP-adress och är inget secure context, så navigator.share och
navigator.clipboard finns inte. Koden tar då else-grenen, och navigator.clipboard.writeText() ger
ett TypeError som fångas av catch.
Det är en bra påminnelse om att även det du faller tillbaka på behöver kontrolleras. Service workers och installation kräver också secure context, så för att testa de delarna på en telefon behöver applikationen ligga på HTTPS.
Fråga: delningen som väntar
Section titled “Fråga: delningen som väntar”Innan delningen ska länken hämtas från en server som är långsam:
shareButton.addEventListener('click', async () => { const response = await fetch('/api/share-link') const { url } = await response.json() await navigator.share({ url })})Ibland fungerar det, ibland inte. Varför?
Aktiveringen från klicket varar bara en kort stund. Tar förfrågan för lång tid har den gått ut när
navigator.share() anropas, och promiset blir rejected med ett NotAllowedError.
Hämta det du behöver innan användaren klickar, så att anropet kan göras direkt i lyssnaren. Den här sortens fel är lätt att missa på en snabb utvecklingsmaskin.
En översikt
Section titled “En översikt”Tabellen visar läget i MDN:s kompatibilitetsdata i november 2026. Stödet för Firefox och Safari gäller utan flaggor.
| API | Gör det möjligt att | Stöd |
|---|---|---|
| Canvas | rita 2D-grafik med JavaScript | Alla |
| WebGL | rita hårdvaruaccelererad 3D-grafik | Alla |
| WebGPU | använda grafikkortet, efterföljaren till WebGL | Chromium, Safari, delvis Firefox |
| Web Animations | styra animationer från JavaScript | Alla |
| Fullscreen | visa ett element i helskärm | Alla, delvis på iPhone |
| Geolocation | läsa enhetens position | Alla |
| Clipboard | läsa från och skriva till urklipp | Alla |
| Gamepad | läsa av spelkontroller | Alla |
| Screen Wake Lock | hindra skärmen från att släckas | Alla |
| WebRTC | skicka ljud, bild och data direkt mellan klienter | Alla |
| MediaRecorder | spela in ljud och bild | Alla |
| Web Share | öppna operativsystemets delningsmeny | Chromium, Safari |
| Payment Request | låta webbläsaren hantera betalningsuppgifter | Chromium, Safari |
| Speech Recognition | tolka tal till text | Varierar, med prefix i Safari |
| WebXR | bygga AR och VR | Chromium |
| Web Bluetooth | prata med Bluetooth-enheter | Chromium |
| WebUSB | prata med USB-enheter | Chromium |
| Web NFC | läsa och skriva NFC-taggar | Chrome på Android |
| EyeDropper | hämta en färg från skärmen | Chromium på dator |
Mönstret är tydligt. Det som rör grafik och enkel interaktion finns i alla webbläsare. Det som ger direkt tillgång till hårdvara finns i stort sett bara i Chromium, eftersom Mozilla och Apple har valt att inte införa de API:erna, bland annat av integritetsskäl.
Några saker som är lätta att missa:
- WebRTC behöver ändå en server. Trafiken kan gå direkt mellan klienterna, men de måste först hitta varandra via en server, till exempel över en WebSocket. Ibland går inte en direkt anslutning att skapa, och då skickas trafiken via en server.
- Gamepad har inga händelser för knappar. Bara
gamepadconnectedochgamepaddisconnectedär händelser. Knapparnas läge läser du av i en loop mednavigator.getGamepads()ochrequestAnimationFrame(). - Drag and Drop API behövs inte i B3. Att flytta ett fönster är enklare med vanliga mushändelser.
API:er kommer och går
Section titled “API:er kommer och går”Ett API som finns i dag finns inte nödvändigtvis kvar. Battery Status API visade batterinivån och togs bort ur Firefox, eftersom värdet kunde användas för att känna igen användare mellan webbplatser. Det finns kvar i Chromium, men har aldrig funnits i Safari. Vibration API har tagits bort ur Firefox och har heller aldrig funnits i Safari. Ambient Light Sensor kräver fortfarande en flagga även i Chromium.
Det är ännu ett skäl att bygga så att applikationen fungerar även utan API:et.
Ett exempel: Canvas
Section titled “Ett exempel: Canvas”<canvas> är en rityta av pixlar. Du ritar med kommandon, och när kommandot har körts finns bara
pixlarna kvar, inga objekt att flytta eller lyssna på. Det skiljer den från SVG, där varje form är ett
element i DOM:en.
Så här kan antalet försök i de senaste memoryspelen visas som staplar:
/** * Draws one bar per game. * * @param {HTMLCanvasElement} canvas - The canvas to draw on. * @param {number[]} attempts - The number of attempts in each game. */function drawHistory(canvas, attempts) { const context = canvas.getContext('2d') const barWidth = canvas.width / attempts.length const highest = Math.max(...attempts)
context.clearRect(0, 0, canvas.width, canvas.height) context.fillStyle = 'rebeccapurple'
attempts.forEach((value, index) => { const barHeight = (value / highest) * canvas.height context.fillRect(index * barWidth, canvas.height - barHeight, barWidth - 2, barHeight) })}<canvas width="300" height="150" role="img" aria-label="Antal försök i de senaste spelen"></canvas>Attributen width och height anger ritytans storlek i pixlar. Storleken i CSS bara skalar resultatet,
så sätter du en annan storlek i CSS blir bilden utdragen eller suddig. Eftersom det bara är pixlar kan
varken skärmläsare eller tangentbord nå något i bilden. role="img" och aria-label beskriver bilden,
och det som går att göra i en canvas behöver också gå att göra med tangentbordet.
För animationer ritar du om i en loop med requestAnimationFrame(). Starta loopen i
connectedCallback() och avbryt den med cancelAnimationFrame() i disconnectedCallback().
Att välja API till B3
Section titled “Att välja API till B3”Listan i B3:s krav är exempel. Tänk igenom några saker innan du väljer:
- Måste det fungera offline? Canvas, Clipboard och Web Animations gör det. Taligenkänning kan kräva nätverk, beroende på webbläsare. I så fall ska användaren få veta det.
- Finns det i webbläsaren där du examineras? Ett API som bara finns i Chromium går bra, om du använder feature detection och visar det i en webbläsare som har stöd.
- Går det att visa? Bygger du på hårdvara som en spelkontroll eller en Bluetooth-enhet, ha den med vid den muntliga examinationen, eller kontakta kursledningen i god tid.
- Känns det i applikationen? En färgpipett i ett ritprogram är bättre än ett API som läggs till bara för att kravet ska bockas av. Du ska kunna förklara vad det gör och varför det sitter där.
Att ta med sig
Section titled “Att ta med sig”- Att vara kapabel betyder att en PWA kan göra sådant som tidigare krävde en installerad app.
- Slå upp stödet på MDN eller Can I use, och använd feature detection i koden.
- Många API:er kräver secure context, användaraktivering eller behörighet.
localhosträknas som säkert, en vanlig IP-adress över HTTP gör det inte. - Fråga om behörighet när användaren behöver funktionen, och hantera ett nej.
- Canvas är pixlar. Rita med kommandon, och tänk på tillgängligheten.
- API:er kan försvinna. Bygg så att applikationen fungerar även utan dem.
Vidare läsning
Section titled “Vidare läsning”- Web APIs på MDN, hela listan.
- Secure contexts och User activation på MDN.
- Canvas API på MDN, med en utförlig guide.
- What PWA Can Do Today, en samling exempel som går att prova.