ранее писал тут — https://1.cbm.ua/?p=4454

Инструкция как создать PWA приложение.
на примере простого PWA приложение с базовым функционалом. Это будет список задач с возможностью работы офлайн.
Создать фал manifest.json — это манифест.
{
"name": "Название вашего приложения",
"short_name": "Короткое название",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#000000",
"icons": [
{
"src": "//fjngqp1mvftjzxfzrdiggafze9wxueam.cdn-freehost.com.ua/icon.png",
"sizes": "192x192",
"type": "image/png"
}
]
}
2. Добавить ссылку на манифест в HTML-код вашей страницы.
<link rel="manifest" href="//fjngqp1mvftjzxfzrdiggafze9wxueam.cdn-freehost.com.ua/manifest.json">
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PWA Todo List</title>
<link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiUFdBIFRvZG8gTGlzdCIsInNob3J0X25hbWUiOiJUb2RvUFdBIiwic3RhcnRfdXJsIjoiLyIsImRpc3BsYXkiOiJzdGFuZGFsb25lIiwiYmFja2dyb3VuZF9jb2xvciI6IiNmZmZmZmYiLCJ0aGVtZV9jb2xvciI6IiM0Mjg1ZjQiLCJpY29ucyI6W3sic3JjIjoiZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCM2FXUjBhRDBpTVRrd0lpQm9aV2xuYUhROUlqRTVNQ0lpSUhabGNuTnBiMjQ5SWpFdU1TSWdlRzFzYm5NOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6SXdNREF2YzNabklqNGdJRHhqYVhKamJHVWdZM2c5SWprMUlpQmplVDBpT1RVaUlISTlJamMxSWlCbWFXeHNQU0lqTkRJNE5XWTBJaTgrSUR4MFpYaDBJSGc5SWprMUlpQjVQU0k1TlNJZ2RHVjRkQzFoYm1Ob2IzSTlJbTFwWkdSc1pTSWdabTl1ZEMxbVlXMXBiSGs5SW1GdWFXRnNJaUJtYVd4c1BTSWpabVptSWo1VVQwUlBQQzkwWlhoMFBpQThMM04yWno0PSIsInNpemVzIjoiMTkweDIxMSIsInR5cGUiOiJpbWFnZS9zdmcreG1sIn1dfQ==">
<meta name="theme-color" content="#4285f4">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 600px;
margin: 0 auto;
background: white;
border-radius: 12px;
box-shadow: 0 8px 32px rgba(0,0,0,0.1);
overflow: hidden;
}
.header {
background: #4285f4;
color: white;
padding: 20px;
text-align: center;
}
.header h1 {
font-size: 24px;
margin-bottom: 5px;
}
.status {
font-size: 14px;
opacity: 0.9;
}
.add-task {
padding: 20px;
border-bottom: 1px solid #eee;
}
.task-input {
width: 100%;
padding: 12px;
border: 2px solid #e0e0e0;
border-radius: 6px;
font-size: 16px;
margin-bottom: 10px;
}
.task-input:focus {
outline: none;
border-color: #4285f4;
}
.add-btn {
background: #4285f4;
color: white;
border: none;
padding: 12px 24px;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
transition: background 0.3s;
}
.add-btn:hover {
background: #3367d6;
}
.tasks-list {
min-height: 200px;
padding: 20px;
}
.task-item {
display: flex;
align-items: center;
padding: 15px;
border-bottom: 1px solid #f0f0f0;
transition: background 0.3s;
}
.task-item:hover {
background: #f8f9fa;
}
.task-item.completed {
opacity: 0.6;
text-decoration: line-through;
}
.task-checkbox {
margin-right: 15px;
cursor: pointer;
}
.task-text {
flex: 1;
font-size: 16px;
}
.delete-btn {
background: #ff4444;
color: white;
border: none;
padding: 8px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
.delete-btn:hover {
background: #cc0000;
}
.empty-state {
text-align: center;
color: #666;
padding: 40px 20px;
}
.install-prompt {
background: #f8f9fa;
border: 1px solid #e0e0e0;
border-radius: 6px;
padding: 15px;
margin: 20px;
text-align: center;
display: none;
}
.install-btn {
background: #34a853;
color: white;
border: none;
padding: 10px 20px;
border-radius: 4px;
cursor: pointer;
margin-top: 10px;
}
@media (max-width: 480px) {
.container {
margin: 0;
border-radius: 0;
min-height: 100vh;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>📝 PWA Todo List</h1>
<div class="status" id="status">Онлайн</div>
</div>
<div class="install-prompt" id="installPrompt">
<div>Установите приложение для лучшего опыта!</div>
<button class="install-btn" id="installBtn">Установить</button>
</div>
<div class="add-task">
<input type="text" class="task-input" id="taskInput" placeholder="Добавить новую задачу...">
<button class="add-btn" id="addBtn">Добавить</button>
</div>
<div class="tasks-list" id="tasksList">
<div class="empty-state">
Нет задач. Добавьте первую задачу!
</div>
</div>
</div>
<script>
// Основная логика приложения
class TodoApp {
constructor() {
this.tasks = this.loadTasks();
this.initEventListeners();
this.renderTasks();
this.updateStatus();
}
initEventListeners() {
document.getElementById('addBtn').addEventListener('click', () => this.addTask());
document.getElementById('taskInput').addEventListener('keypress', (e) => {
if (e.key === 'Enter') this.addTask();
});
// Обновление статуса подключения
window.addEventListener('online', () => this.updateStatus());
window.addEventListener('offline', () => this.updateStatus());
}
addTask() {
const input = document.getElementById('taskInput');
const text = input.value.trim();
if (text) {
const task = {
id: Date.now(),
text: text,
completed: false,
createdAt: new Date().toISOString()
};
this.tasks.push(task);
this.saveTasks();
this.renderTasks();
input.value = '';
}
}
toggleTask(id) {
const task = this.tasks.find(t => t.id === id);
if (task) {
task.completed = !task.completed;
this.saveTasks();
this.renderTasks();
}
}
deleteTask(id) {
this.tasks = this.tasks.filter(t => t.id !== id);
this.saveTasks();
this.renderTasks();
}
renderTasks() {
const container = document.getElementById('tasksList');
if (this.tasks.length === 0) {
container.innerHTML = '<div class="empty-state">Нет задач. Добавьте первую задачу!</div>';
return;
}
container.innerHTML = this.tasks.map(task => `
<div class="task-item ${task.completed ? 'completed' : ''}">
<input type="checkbox" class="task-checkbox"
${task.completed ? 'checked' : ''}
onchange="app.toggleTask(${task.id})">
<div class="task-text">${task.text}</div>
<button class="delete-btn" onclick="app.deleteTask(${task.id})">Удалить</button>
</div>
`).join('');
}
saveTasks() {
localStorage.setItem('pwa-tasks', JSON.stringify(this.tasks));
}
loadTasks() {
const saved = localStorage.getItem('pwa-tasks');
return saved ? JSON.parse(saved) : [];
}
updateStatus() {
const status = document.getElementById('status');
status.textContent = navigator.onLine ? 'Онлайн' : 'Офлайн';
status.style.color = navigator.onLine ? '#4CAF50' : '#FF9800';
}
}
// Service Worker регистрация
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('data:application/javascript;base64,Y29uc3QgQ0FDSEVfTkFNRSA9ICd0b2RvLXB3YS12MSc7CmNvbnN0IHVybHNUb0NhY2hlID0gWycvJ107CgpzZWxmLmFkZEV2ZW50TGlzdGVuZXIoJ2luc3RhbGwnLCBldmVudCA9PiB7CiAgZXZlbnQud2FpdFVudGlsKAogICAgY2FjaGVzLm9wZW4oQ0FDSEVfTkFNRSkKICAgICAgLnRoZW4oY2FjaGUgPT4gY2FjaGUuYWRkQWxsKHVybHNUb0NhY2hlKSkKICApOwp9KTsKCnNlbGYuYWRkRXZlbnRMaXN0ZW5lcignZmV0Y2gnLCBldmVudCA9PiB7CiAgZXZlbnQucmVzcG9uZFdpdGgoCiAgICBjYWNoZXMubWF0Y2goZXZlbnQucmVxdWVzdCkKICAgICAgLnRoZW4ocmVzcG9uc2UgPT4gcmVzcG9uc2UgfHwgZmV0Y2goZXZlbnQucmVxdWVzdCkpCiAgKTsKfSk7');
}
// PWA установка
let deferredPrompt;
const installPrompt = document.getElementById('installPrompt');
const installBtn = document.getElementById('installBtn');
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
installPrompt.style.display = 'block';
});
installBtn.addEventListener('click', async () => {
if (deferredPrompt) {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
deferredPrompt = null;
installPrompt.style.display = 'none';
}
});
// Инициализация приложения
const app = new TodoApp();
</script>
</body>
</html>
Создал простое PWA приложение — список задач с следующими возможностями:
Основные функции:
- Добавление задач — можно добавлять новые задачи
- Отметка выполнения — отмечать задачи как выполненные
- Удаление задач — удалять ненужные задачи
- Сохранение данных — задачи сохраняются в localStorage
PWA возможности:
- Офлайн работа — приложение работает без интернета
- Установка — можно установить как обычное приложение
- Статус подключения — показывает онлайн/офлайн статус
- Адаптивный дизайн — хорошо выглядит на мобильных устройствах
Технические особенности:
- Service Worker для кэширования
- Web App Manifest для установки
- Современный UI с градиентами и анимациями
- Работа с LocalStorage для хранения данных
Приложение готово к использованию! Вы можете открыть его в браузере и установить как PWA для получения нативного опыта использования.
