Chcete vytvořit web, který si uživatelé mohou přidat na plochu telefonu, pohodlně spouštět jako aplikaci a využívat jeho vybrané funkce i bez internetu? Právě to umožňuje PWA aplikace (Progressive Web App). Kombinuje dostupnost webových stránek s funkcemi, které lidé znají z mobilních aplikací. V Expert Dev při vývoji webových aplikací řešíme nejen samotné programování, ale také rychlost, použitelnost a další rozvoj výsledného řešení.
Jak vytvořit PWA aplikaci v praxi? V tomto návodu si jednotlivé kroky ukážeme na jednoduchém seznamu úkolů. Připravíme základní HTML strukturu, nastavíme Web App Manifest, naprogramujeme Service Worker a zajistíme dostupnost aplikace offline. Následně vysvětlíme instalaci na různá zařízení, testování a úpravy, které potřebuje skutečný firemní projekt.
Co je PWA aplikace a jak funguje?
PWA neboli představuje webovou aplikaci, která využívá moderní možnosti prohlížečů. Uživatel ji může otevřít prostřednictvím běžné URL adresy a v podporovaných prohlížečích také nainstalovat do zařízení. Po spuštění z ikony na ploše pak může fungovat v samostatném okně bez běžných ovládacích prvků prohlížeče. Základ PWA tvoří webové technologie, jako jsou HTML, CSS a JavaScript. Pokročilejší chování zajišťují především dva prvky:
Web App Manifest – Soubor s informacemi o aplikaci, jejím názvu, ikonách, úvodní adrese a způsobu zobrazení po instalaci.
Service Worker - JavaScriptový skript, který dokáže obsluhovat síťové požadavky, pracovat s mezipamětí (cache) a zpřístupnit vybraný obsah offline.
Samotná instalovatelnost ovšem automaticky neznamená plnohodnotný offline režim. Ten musí vývojář naprogramovat podle funkcí konkrétního projektu. Stejně tak se dostupné možnosti liší mezi operačními systémy a prohlížeči. Pro firmu může takové řešení znamenat například klientský portál, rezervační systém nebo interní nástroj, ke kterému se zaměstnanci pravidelně vracejí. Podrobnější obchodní přínosy rozebíráme v samostatném článku 5 důvodů, proč jsou PWA aplikace budoucnost online byznysu. Zde se zaměříme především na samotnou tvorbu.
Co potřebujete před vytvořením PWA aplikace?
Než začnete programovat, rozhodněte, které funkce má aplikace nabídnout a zda skutečně potřebujete offline provoz. U jednoduchého projektu může stačit uložit základní rozhraní do cache. U firemního systému, kde uživatelé upravují záznamy bez připojení, musíte navrhnout také lokální ukládání změn a jejich následnou synchronizaci. Pro vytvoření první PWA si připravte:
Základní znalost HTML, CSS a JavaScriptu - Pro náš příklad nepotřebujete žádný framework.
Editor zdrojového kódu - Použít můžete například Visual Studio Code.
Lokální webový server - Aplikaci budete spouštět přes localhost, nikoliv přímým otevřením HTML souboru.
Ikony aplikace - Připravte minimálně PNG obrázky o rozměrech 192 × 192 a 512 × 512 pixelů.
Moderní prohlížeč s vývojářskými nástroji - Pro první testování poslouží například Google Chrome nebo Microsoft Edge.
Pokud zatím nemáte funkční webovou aplikaci a začínáte úplně od začátku, vyplatí se nejprve promyslet celý projekt. Jednotlivé fáze od zadání po spuštění popisujeme v článku Vývoj webové aplikace od nápadu po spuštění.
Krok 1: Vytvořte základní strukturu PWA
Začneme jednoduchou aplikací pro ukládání úkolů. Uživatel zadá úkol, přidá jej do seznamu a může ho později odstranit. Údaje uložíme přímo do jeho prohlížeče, takže seznam zůstane dostupný i bez internetového připojení. Vytvořte složku pwa-ukoly a připravte následující soubory:
pwa-ukoly/
├── index.html
├── app.js
├── manifest.webmanifest
├── sw.js
└── icons/
├── icon-192.png
└── icon-512.png
Hlavní stránku vytvoříme v souboru index.html. Obsahuje jednoduchý formulář, seznam úkolů a odkazy na JavaScript a manifest.
<!doctype html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#1768a6">
<title>Moje úkoly – PWA aplikace</title>
<link rel="manifest" href="./manifest.webmanifest">
<script src="./app.js" defer></script>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 40rem;
margin: 3rem auto;
padding: 0 1rem;
}
form {
display: flex;
flex-wrap: wrap;
gap: .5rem;
}
input {
flex: 1;
min-width: 12rem;
padding: .65rem;
}
button {
padding: .65rem;
cursor: pointer;
}
li {
margin: .6rem 0;
}
</style>
</head>
<body>
<main>
<h1>Moje úkoly</h1>
<p>Úkoly ukládáme do tohoto prohlížeče.</p>
<form id="task-form">
<label for="task-input">Nový úkol</label>
<input id="task-input"
name="task"
maxlength="120"
required>
<button type="submit">Přidat úkol</button>
</form>
<ul id="tasks"></ul>
</main>
</body>
</html>
Ukázka záměrně používá pouze základní HTML a CSS. Pro složitější projekt můžete využít React, Vue, Angular nebo jinou technologii, ale postup vytvoření PWA zůstává v hlavních principech podobný.
Výsledek prvního kroku: Máte připravené uživatelské rozhraní. Formulář zatím s úkoly nepracuje, protože jeho funkčnost doplníme pomocí JavaScriptu.

Krok 2: Nastavte Web App Manifest
Aby prohlížeč věděl, jak má aplikaci zobrazit při instalaci, potřebuje její základní metadata. K tomu slouží Web App Manifest, který zapisujeme ve formátu JSON. Vytvořte soubor manifest.webmanifest a vložte do něj následující nastavení:
{
"name": "Moje úkoly",
"short_name": "Úkoly",
"lang": "cs",
"start_url": "./",
"scope": "./",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#1768a6",
"icons": [
{
"src": "icons/icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
Co znamenají jednotlivá nastavení?
Nejdůležitější jsou následující položky:
name a short_name určují název aplikace a jeho zkrácenou variantu.
start_url nastavuje adresu, kterou prohlížeč otevře při spuštění aplikace.
scope vymezuje adresy, které patří do aplikačního prostředí.
display: "standalone" umožňuje zobrazení aplikace v samostatném okně.
background_color a theme_color určují barvy používané v podporovaných částech uživatelského prostředí.
icons obsahuje cesty k ikonám a jejich rozměry.
Uvedené cesty fungují pro projekt, jehož soubory leží ve stejné složce. Pokud aplikaci nasadíte do jiné adresářové struktury, upravte je podle skutečného umístění. Ikony vytvořte z vlastního grafického návrhu a uložte je pod uvedenými názvy. Pro výslednou firemní aplikaci doporučujeme také kvalitní adaptivní ikony s variantou maskable, které lépe využijí prostor na různých zařízeních.
Na co si dát pozor: Manifest sám o sobě neukládá stránky offline. Jeho úkolem je především popsat aplikaci a její instalační vlastnosti. Dostupnost obsahu bez internetu vyřešíme v dalších krocích.
Krok 3: Naprogramujte funkce aplikace v JavaScriptu
Nyní oživíme formulář. Pro ukládání úkolů využijeme localStorage, tedy jednoduché úložiště přímo v prohlížeči. V našem demonstračním projektu nepotřebujeme databázi ani serverové API. Do souboru app.js vložte následující kód:
const STORAGE_KEY = "pwa-ukoly-v1";
const form = document.querySelector("#task-form");
const input = document.querySelector("#task-input");
const list = document.querySelector("#tasks");
let tasks;
try {
const saved = JSON.parse(
localStorage.getItem(STORAGE_KEY) || "[]"
);
tasks = Array.isArray(saved) ? saved : [];
} catch {
tasks = [];
}
function renderTasks() {
list.replaceChildren();
tasks.forEach((task, index) => {
const item = document.createElement("li");
const label = document.createElement("span");
label.textContent = task;
const removeButton = document.createElement("button");
removeButton.type = "button";
removeButton.textContent = "Smazat";
removeButton.addEventListener("click", () => {
tasks.splice(index, 1);
localStorage.setItem(
STORAGE_KEY,
JSON.stringify(tasks)
);
renderTasks();
});
item.append(label, " ", removeButton);
list.append(item);
});
}
form.addEventListener("submit", (event) => {
event.preventDefault();
const task = input.value.trim();
if (!task) return;
tasks.push(task);
localStorage.setItem(
STORAGE_KEY,
JSON.stringify(tasks)
);
form.reset();
renderTasks();
});
renderTasks();
Skript reaguje na odeslání formuláře, ukládá úkoly do seznamu a následně aktualizuje zobrazení. Po opětovném otevření aplikace načte uložené položky z localStorage. Pro jednoduchý seznam nebo uživatelské nastavení je tento postup dostatečný. Větší aplikace na míru však zpravidla potřebují robustnější práci s daty. Pro rozsáhlejší offline úložiště lze využít například IndexedDB, zatímco synchronizaci mezi zařízeními musí zajistit odpovídající serverové řešení. Výhodou ukázkového projektu je, že můžeme všechny další kroky otestovat na konkrétní funkci, nikoliv pouze na statické stránce.
Krok 4: Vytvořte Service Worker a zprovozněte offline režim
Service Worker tvoří důležitou součást PWA, pokud potřebujete obsluhovat požadavky a poskytovat obsah bez připojení. Prohlížeč jej spouští odděleně od hlavní stránky a umožňuje mu pracovat například s Cache Storage. Vytvořte soubor sw.js. V naší ukázce použijeme jednoduchý přístup: při instalaci Service Workeru uložíme základní soubory aplikace do cache a při dalších požadavcích nejdříve zkontrolujeme jejich dostupnost v úložišti.
const CACHE_PREFIX = "pwa-ukoly-";
const CACHE_NAME = CACHE_PREFIX + "v1";
const APP_FILES = [
"./",
"./index.html",
"./app.js",
"./manifest.webmanifest",
"./icons/icon-192.png",
"./icons/icon-512.png"
];
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open(CACHE_NAME).then((cache) => {
return cache.addAll(APP_FILES);
})
);
});
self.addEventListener("activate", (event) => {
event.waitUntil(
caches.keys().then((names) => {
return Promise.all(
names
.filter((name) =>
name.startsWith(CACHE_PREFIX) &&
name !== CACHE_NAME
)
.map((name) => caches.delete(name))
);
})
);
});
self.addEventListener("fetch", (event) => {
if (event.request.method !== "GET") return;
const url = new URL(event.request.url);
if (url.origin !== self.location.origin) return;
event.respondWith(
caches.open(CACHE_NAME).then(async (cache) => {
const saved = await cache.match(event.request);
return saved || fetch(event.request);
})
);
});
Jak Service Worker zaregistrovat?
Samotné vytvoření souboru nestačí. Prohlížeči musíme říct, že má skript používat. Na konec souboru app.js proto přidejte registraci:
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("./sw.js")
.catch((error) => {
console.error(
"Registrace Service Workeru selhala:",
error
);
});
});
}
Prohlížeč následně stáhne Service Worker, provede jeho instalaci a uloží soubory uvedené v seznamu APP_FILES. V tomto konkrétním příkladu bude aplikace po úspěšném uložení souborů schopná načíst své základní rozhraní offline. Úkoly zůstanou dostupné díky localStorage, které jsme nastavili v předchozím kroku. Počítejte však s tím, že před prvním použitím offline režimu musí prohlížeč aplikaci alespoň jednou úspěšně načíst a dokončit instalaci Service Workeru. Uvedený kód představuje jednoduchou demonstrační implementaci. Nespravuje automaticky dynamické API odpovědi ani neřeší synchronizaci dat se serverem.
Krok 5: Zvolte správnou strategii cachování a aktualizací
Při vývoji skutečné PWA aplikace nestačí ukládat všechny požadavky stejným způsobem. Některé soubory se mění jen při nasazení nové verze, zatímco jiné informace musí odpovídat aktuálnímu stavu systému. Vývojáři proto používají několik strategií práce s cache:
