Рекомендации по разработке прогрессивных веб приложений (PWA)
Tags: pwa, javascript, angular
Published: 2023-06-22 13:26:45

## Введение

Прогрессивные веб-приложения (PWA) являются мощным инструментом для разработки, который позволяет создавать веб-приложения с функциональностью, очень близкой к нативным мобильным приложениям. Это означает, что пользователи могут пользоваться приложением даже в офлайн-режиме, получать push-уведомления и наслаждаться адаптивным дизайном, который прекрасно выглядит на различных устройствах.

Данные практические рекомендации предназначены для разработчиков, которые хотят создать прогрессивное веб-приложение с использованием JavaScript и Angular. Рекомендации включают обзор ключевых принципов и технологий, рекомендации по их применения, а также примеры их применения, использую JavaScript и фреймворк Angular.

В следующих разделах будут представлены подробные рекомендации, охватывающие различные аспекты разработки прогрессивных веб-приложений с использованием JavaScript и Angular. По мере изучения данных рекомендаций, разработчики получат все необходимые инструменты и знания для создания современных и высококачественных прогрессивных веб-приложений для мобильных устройств.

## Рекомендации

**Разработка с учетом прогрессивной улучшаемости**

1. **Обеспечьте базовую функциональность**. В начале разработки сосредоточьтесь на создании базовой функциональности вашего приложения, которая будет работать на всех устройствах и браузерах. Гарантируйте, что пользователи могут использовать основные функции приложения без проблем.
2. **Используйте постепенное улучшение**. По мере доступности новых возможностей браузеров и устройств, постепенно добавляйте дополнительные функции и улучшения к вашему приложению. Например, можете использовать адаптивный дизайн, чтобы приложение выглядело и работало оптимально на различных экранах, добавлять интерактивность с помощью JavaScript и использовать новые API для улучшения функциональности.
3. **Учтите особенности различных браузеров и устройств**. Разные браузеры и устройства могут иметь различную поддержку технологий и возможностей. Учтите эти различия и обеспечьте, чтобы ваше приложение работало без проблем на наиболее распространенных браузерах и устройствах. Проводите тестирование и отладку на различных платформах, чтобы убедиться в совместимости и правильном функционировании.
4. **Обновляйте и поддерживайте приложение**. После выпуска приложения продолжайте поддерживать и обновлять его, чтобы учитывать изменения в технологиях и поведении пользователей. Регулярно проверяйте и исправляйте возможные проблемы совместимости, добавляйте новые функции и оптимизируйте производительность.

**Адаптивный дизайн и мобильная оптимизация**
1. **Проектируйте с учетом различных экранов**. При разработке приложения учитывайте разнообразие устройств и экранов, на которых оно будет запускаться. Используйте гибкий макет и раскладку, которые могут адаптироваться к разным размерам экранов, начиная от мобильных устройств до настольных компьютеров.
2. **Оптимизируйте загрузку контента**. Обратите особое внимание на скорость загрузки вашего приложения на мобильных устройствах. Убедитесь, что размеры изображений и других медиа-ресурсов оптимизированы для быстрой загрузки. Используйте сжатие, кэширование и другие методы для улучшения производительности загрузки.
3. **Тестируйте на различных устройствах и браузерах**. Проверьте, как ваше приложение отображается и работает на различных мобильных устройствах и в разных браузерах. Учтите особенности каждой платформы и убедитесь, что ваше приложение корректно отображается и функционирует на всех популярных устройствах.
4. **Используйте медиа-запросы**. Используйте CSS медиа-запросы для создания адаптивного дизайна, который реагирует на различные размеры экранов. Медиа-запросы позволяют вам применять разные стили для разных устройств, что помогает создать оптимальный пользовательский опыт на каждом устройстве.
5. **Тестируйте производительность**. Проверьте производительность вашего приложения на мобильных устройствах. Используйте инструменты для анализа производительности, чтобы выявить узкие места и оптимизировать работу приложения для достижения быстрой загрузки и плавной работы на мобильных устройствах.

**Оффлайн-работа**
1. **Используйте Service Workers**. Service Workers - это ключевая технология для обеспечения офлайн-работы в прогрессивных веб-приложениях. Используйте Service Workers для кэширования данных и ресурсов, а также для управления сетевыми запросами. Разработайте Service Worker, который будет обрабатывать запросы, когда приложение находится в офлайн-режиме, и использовать сохраненные ресурсы из кэша.
2. **Кэшируйте критические ресурсы**. Определите критически важные ресурсы, которые должны быть доступны приложению даже в офлайн-режиме, и кэшируйте их с помощью Service Worker. Это может включать HTML-шаблоны, стили, скрипты и изображения, необходимые для основной функциональности приложения. При наличии кэшированных ресурсов приложение сможет продолжать работать в офлайн-режиме без потери ключевых функций.
3. **Обрабатывайте офлайн-события и ошибки**. При разработке приложения учтите возможность возникновения офлайн-событий и ошибок при сетевых запросах. Обработайте эти события, предоставив пользователю соответствующую обратную связь и возможность повторить запросы или выполнить действия, когда соединение сети восстановится.
4. **Сохраняйте данные для офлайн-доступа**. Если ваше приложение работает с данными, предусмотрите механизм сохранения данных для офлайн-доступа. Можно использовать локальное хранилище браузера или другие механизмы хранения данных на устройстве пользователя. Это позволит пользователям взаимодействовать с данными и продолжать работать с приложением, даже когда они не имеют подключения к интернету.
5. **Обеспечьте синхронизацию данных**. Если пользователь внес изменения в данные в офлайн-режиме, предусмотрите механизм синхронизации этих изменений с сервером, когда соединение сети восстановится. Это позволит сохранить целостность данных и обеспечить согласованность между различными устройствами и сеансами работы с приложением.
6. **Предупреждайте об офлайн-режиме**. Информируйте пользователей о текущем статусе соединения и возможности работы в офлайн-режиме. Предупреждайте пользователей о потенциальных ограничениях и предоставляйте инструкции по действиям, которые они могут выполнить в офлайн-режиме.

**Нативные возможности**
1. **Используйте платформенные API**. В разработке PWA приложений можно использовать нативные возможности платформы, на которой они выполняются. Платформенные API предоставляют доступ к широкому спектру функциональности, включая камеру, геолокацию, датчики устройства и многое другое. Использование платформенных API позволяет вам создавать более мощные и интегрированные приложения, которые лучше соответствуют потребностям пользователей.
2. **Изучите документацию**. Чтобы эффективно использовать нативные возможности, необходимо ознакомиться с документацией для конкретной платформы, на которой вы разрабатываете приложение. Это поможет вам понять, какие функции доступны, как их использовать и какие ограничения существуют. Изучение документации также поможет вам узнать о лучших практиках и рекомендациях для разработки с использованием нативных возможностей.
3. **Поддерживайте кроссплатформенность**. Если ваше PWA приложение предназначено для работы на разных платформах, убедитесь, что вы создаете его с учетом переносимости. Обратите внимание на различия в нативных возможностях между платформами и разработайте гибкую архитектуру, которая позволит вам легко адаптировать код для разных платформ. Используйте паттерны проектирования и подходы, которые способствуют переносимости и уменьшению зависимости от конкретной платформы.
4. **Тестируйте на разных устройствах**. При использовании нативных возможностей важно тестировать приложение на различных устройствах и платформах. Учтите, что функции, которые работают на одной платформе, могут не работать или иметь ограничения на других. Тестирование на реальных устройствах позволит вам убедиться, что ваше приложение взаимодействует с нативными возможностями правильно и без ошибок.

**Безопасность**
1. **Проверка входных данных**. Одним из основных аспектов безопасности в PWA приложениях является проверка входных данных. Убедитесь, что все данные, полученные от пользователей или из внешних источников, проходят проверку на наличие вредоносного кода или нежелательных символов. Используйте механизмы фильтрации и валидации данных, чтобы предотвратить возможность инъекций или атак межсайтового скриптинга (XSS).
2. **Защита от CSRF**. Cross-Site Request Forgery (CSRF) является уязвимостью, когда злоумышленник пытается выполнить несанкционированный запрос от имени аутентифицированного пользователя. Для защиты от CSRF атак, рекомендуется использовать механизмы, такие как генерация и проверка CSRF токенов, чтобы убедиться, что запросы происходят от правильного и аутентифицированного пользователя.
3. **Обеспечение безопасности соединения**. При разработке PWA приложений обеспечение безопасности соединения является критическим аспектом. Используйте протокол HTTPS для защиты передаваемых данных от перехвата и изменения. Убедитесь, что все обмены данными между клиентом и сервером происходят по защищенному соединению.
4. **Управление доступом и авторизация**. Ограничьте доступ к конфиденциальным или привилегированным функциям вашего приложения только аутентифицированным пользователям. Реализуйте механизмы аутентификации и авторизации для контроля доступа и проверки прав пользователя при выполнении определенных действий.
5. **Обновление и устранение уязвимостей**. При разработке PWA приложений регулярно обновляйте используемые библиотеки, фреймворки и зависимости. Важно следить за новыми обновлениями и выпусками, которые могут содержать исправления безопасности или устранение известных уязвимостей. Также регулярно проверяйте свое приложение на уязвимости с помощью специализированных инструментов или услуг безопасности.
6. **Защита хранилища данных**. Если ваше PWA приложение использует локальное хранилище или кэш для сохранения данных, обеспечьте безопасность этих данных. Храните конфиденциальные данные в зашифрованном виде и применяйте меры безопасности, чтобы предотвратить несанкционированный доступ или изменение данных.

**Обновление и обслуживание**
1. **Постоянное обновление**. Следите за актуальностью вашего приложения и его зависимостей. Регулярно выпускайте обновления, включающие исправления ошибок, улучшения производительности и новые функции. Пользователи ожидают, что приложения будут обновляться и соответствовать последним стандартам и требованиям.
2. **Использование механизмов автообновления**. Интегрируйте механизмы автоматического обновления в ваше приложение. Это позволит пользователям получать обновления без необходимости ручной установки новых версий. Service Workers могут быть использованы для автоматического обновления кэшированных ресурсов, а механизмы обновления браузера могут предложить обновление самого приложения.
3. **Тестирование перед выпуском обновлений**. Перед выпуском новых версий приложения проводите тщательное тестирование. Убедитесь, что все функции работают правильно, исправлены все ошибки, и производительность соответствует требованиям. Тестирование поможет предотвратить возможные проблемы и негативное впечатление у пользователей.
4. **Мониторинг производительности и ошибок**. Реализуйте механизмы мониторинга производительности и ошибок в вашем приложении. Это позволит отслеживать производительность и обнаруживать потенциальные проблемы. Используйте аналитику, журнал ошибок и мониторинг загрузки страницы для непрерывного улучшения и оптимизации вашего приложения.
5. **Сообщение о доступности обновлений**. Информируйте пользователей о наличии новых обновлений в приложении. Это можно сделать с помощью уведомлений, оповещений или встроенных механизмов обновления. Убедитесь, что пользователи осведомлены о новых функциях, исправлениях и улучшениях, чтобы они могли вовремя обновить свои приложения.

## Примеры
В примерах показаны отрывки кода Angular приложений, а также используются различные дополнительные npm пакеты.

**Разработка с учетом прогрессивной улучшаемости**
Примером поэтапной улучшаемости может служить этот фрагмент кода:

```javascript
<head>
    <title>Мое PWA приложение</title>
    <link rel="manifest" href="/manifest.json" />
    <script>
        if ('serviceWorker' in navigator) {
            window.addEventListener('load', function () {
                navigator.serviceWorker
                    .register('/sw.js')
                    .then(function (registration) {
                        console.log(
                            'Service Worker зарегистрирован:',
                            registration
                        );
                    })
                    .catch(function (error) {
                        console.log(
                            'Ошибка при регистрации Service Worker:',
                            error
                        );
                    });
            });
        }
    </script>
</head>
```

Здесь мы проверяем доступен ли serviceWorker в нашем браузере и если доступен, то регистрируем его. Также по аналогии можно делать с различными нативными методами, такими как геолокация, пуш уведомления и другими. Если метод доступен, то можем его использовать и, следовательно, улучшать пользовательский опыт. Если недоступен - то стараться дать пользователю максимально комфортный опыт даже без этого метода.

**Адаптивный дизайн и мобильная оптимизация**

```javascript
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    /* Общие стили */
    body {
      font-family: Arial, sans-serif;
      margin: 0;
      padding: 0;
    }
    
    /* Стили для мобильных устройств */
    @media (max-width: 480px) {
      .container {
        width: 100%;
        padding: 10px;
      }
      
      h1 {
        font-size: 24px;
      }
      
      p {
        font-size: 16px;
        line-height: 1.5;
      }
    }
    
    /* Стили для планшетов */
    @media (min-width: 481px) and (max-width: 1024px) {
      .container {
        width: 80%;
        padding: 20px;
      }
      
      h1 {
        font-size: 36px;
      }
      
      p {
        font-size: 18px;
        line-height: 1.6;
      }
    }
    
    /* Стили для десктопов */
    @media (min-width: 1025px) {
      .container {
        width: 60%;
        padding: 40px;
      }
      
      h1 {
        font-size: 48px;
      }
      
      p {
        font-size: 20px;
        line-height: 1.7;
      }
    }
  </style>
</head>
<body>
  <div class="container">
    <h1>Заголовок</h1>
    <p>Это адаптивный текст. Он будет менять размер и расположение в зависимости от размера экрана.</p>
  </div>
</body>
</html>

```

Здесь мы в CSS стилях с помощью тэга @media задаем размер элементов в зависимости от размеров экрана. Также в некоторых случаях мы задаем размер в процентах, а не конкретными величинами.

**Оффлайн-работа**

Оффлайн-работа приложения достигается за счет кэширования данных. Рассмотрим как включить кэширование на примере PWA приложения на Angular.

1) Установите пакет _@angular/service-worker_
`npm install @angular/service-worker`
2) Создайте файл _ngsw-config.json_

```javascript
{
  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      "resources": {
        "files": [
          "/favicon.ico",
          "/index.html",
          "/manifest.webmanifest",
          "/*.css",
          "/*.js"
        ]
      }
    },
    {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)"
        ]
      }
    }
  ],
  "dataGroups": [
    {
      "name": "api-backend",
      "urls": [
        "/api"
      ],
      "cacheConfig": {
        "strategy": "freshness",
        "maxSize": 100,
        "maxAge": "3d"
      }
    }
  ]
}
```
3) В файле _app.module.ts_ добавьте следующий код для включения сервис-воркера

```javascript
import { NgModule } from '@angular/core';
import { ServiceWorkerModule } from '@angular/service-worker';
import { environment } from '../environments/environment';

@NgModule({
  // ...
  imports: [
    // ...
    ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })
  ],
  // ...
})
export class AppModule { }
```
4) Теперь для всех запросов с форматом ссылки, который мы указали в _ngsw-config.json_ (мы указали _/api_) у нас будет применено кэширование

```javascript
import { Component } from '@angular/core';
import { Observable } from 'rxjs';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-example',
  template: `
    <div *ngIf="data$ | async as data">{{ data }}</div>
  `
})
export class ExampleComponent {
  data$: Observable<any> = this.http.get('https://api.example.com/api/data');

  constructor(private http: HttpClient) {}
}
```

**Нативные возможности**

1) Установите пакет _sw-push_
`npm install sw-push`
2) В файл компонента, где вы хотите запросить разрешения на пуш уведомления добавьте следующий код

```javascript
import { Component } from '@angular/core';
import { ApiService } from '../../../../backend/api.service';
import { SwPush } from '@angular/service-worker';


export class WeatherComponent {
  constructor(private readonly apiService: ApiService, private readonly swPush: SwPush) {
    if (
      Notification &&
      Notification.permission !== 'granted' &&
      window.matchMedia('(display-mode: standalone)').matches
    ) {
      Notification.requestPermission().then((res) => {
        if (res === 'granted') {
          this.swPush
            .requestSubscription({
              serverPublicKey: serverPublicKey,
            })
            .then((sub: any) => {
              const convertedSub = JSON.parse(JSON.stringify(sub)); // без этой махинации не удается получить keys
              this.apiService
                .saveNotificationKeys({
                  endpoint: convertedSub.endpoint,
                  p256dh: convertedSub.keys.p256dh,
                  auth: convertedSub.keys.auth,
                })
                .subscribe((res) => console.log(res));
            })
            .catch((err) => console.log(err));
        }
      });
    }
  }
}
```

Обратите внимание, что для полноценной работы пуш-уведомлений требуется настроить серверную часть для отправки уведомлений на уникальные подписки. В приведенном выше коде представлены только клиентские шаги для регистрации подписки и отправки данных на сервер.

Также, убедитесь, что ваше приложение имеет действительный сертификат HTTPS, поскольку пуш-уведомления требуют безопасного соединения. Уведомления на IOS доступны только с версии 16.4.0.

**Безопасность**

Примеры мер для обеспечения безопасности клиентской части PWA приложения

1) Защита от XSS (межсайтовый скриптинг)

Angular предоставляет встроенные механизмы для защиты от CSRF атак. Для обеспечения безопасности при отправке HTTP запросов, рекомендуется использовать Angular HttpClient и установить CSRF токен через HTTP заголовок `X-XSRF-TOKEN`.

```javascript
import { HttpClientModule, HttpClient, HttpHeaders } from '@angular/common/http';
import { Component } from '@angular/core';

@Component({
  selector: 'app-my-component',
  template: '<button (click)="sendRequest()">Send Request</button>'
})
export class MyComponent {
  constructor(private http: HttpClient) { }

  sendRequest() {
    const url = 'https://api.example.com/data';
    const data = { key: 'value' };
    const headers = new HttpHeaders().set('X-CSRF-Token', 'your-csrf-token');

    this.http.post(url, data, { headers }).subscribe(
      response => {
        // Обработка успешного ответа
      },
      error => {
        // Обработка ошибки
      }
    );
  }
}
```

В данном примере используется `HttpClient` для отправки HTTP запроса с установленным заголовком `X-CSRF-Token`. Заголовок должен содержать CSRF токен, который должен быть предоставлен сервером в ответ на предыдущий запрос аутентификации пользователя.

2) Фильтрация и валидация пользовательского ввода

```javascript
import { Component } from '@angular/core';
import { FormControl, Validators } from '@angular/forms';

@Component({
  selector: 'app-my-component',
  template: '<input [formControl]="usernameControl">'
})
export class MyComponent {
  usernameControl = new FormControl('', [
    Validators.required,
    Validators.pattern('[a-zA-Z0-9]*')
  ]);
}
```

В этом примере используется Angular Forms и `FormControl` для валидации и фильтрации пользовательского ввода. Валидаторы `required` и `pattern` используются для проверки обязательности поля и задания шаблона ввода.

3) Защита данных на клиентской стороне

Для обеспечения безопасности данных на клиентской стороне можно использовать механизм шифрования. Вот пример использования CryptoJS для шифрования данных.

```javascript
import { Component } from '@angular/core';
import * as CryptoJS from 'crypto-js';

@Component({
  selector: 'app-my-component',
  template: '<button (click)="encryptData()">Encrypt Data</button>'
})
export class MyComponent {
  secretKey = 'your-secret-key';

  encryptData() {
    const data = 'Hello, world!';
    const encryptedData = CryptoJS.AES.encrypt(data, this.secretKey).toString();

    console.log('Encrypted Data:', encryptedData);
  }
}
```

В этом примере используется CryptoJS для шифрования данных с использованием алгоритма AES. Зашифрованные данные могут быть отправлены на сервер или сохранены локально, а затем расшифрованы с использованием того же секретного ключа.

4) Аутентификация и авторизация

Для обеспечения безопасности веб-приложения важно иметь механизмы аутентификации и авторизации. Angular предоставляет мощные инструменты для реализации таких механизмов, например, использование JSON Web Token (JWT) для аутентификации и ролевой базированной авторизации.

```javascript
import { Component } from '@angular/core';
import { AuthService } from './auth.service';

@Component({
  selector: 'app-my-component',
  template: `
    <button *ngIf="authService.isAuthenticated()" (click)="logout()">Logout</button>
    <div *ngIf="authService.isAuthenticated()">
      Welcome, {{ authService.getUsername() }}!
    </div>
    <form *ngIf="!authService.isAuthenticated()" (submit)="login()">
      <input type="text" [(ngModel)]="username" name="username" placeholder="Username">
      <input type="password" [(ngModel)]="password" name="password" placeholder="Password">
      <button type="submit">Login</button>
    </form>
  `
})
export class MyComponent {
  username: string;
  password: string;

  constructor(private authService: AuthService) { }

  login() {
    this.authService.login(this.username, this.password).subscribe(
      response => {
        // Успешная аутентификация
      },
      error => {
        // Ошибка аутентификации
      }
    );
  }

  logout() {
    this.authService.logout();
  }
}
```

В этом примере используется сервис `AuthService`, который предоставляет методы для аутентификации и авторизации. Форма входа отображается только для неаутентифицированных пользователей, а кнопка выхода - только для аутентифицированных пользователей.

Учитывайте, что эти примеры лишь некоторые из мер безопасности, которые могут быть применены в PWA Angular приложении. Важно принимать все меры предосторожности, чтобы защитить приложение от различных уязвимостей и атак, а также следовать рекомендациям безопасности Angular и обновлять приложение и его зависимости регулярно.

**Обновление и обслуживание**

Рассмотри пример обновления PWA Angular приложения с помощью Service Worker (SW) и функциональности SW Update.

1) В файле `app.component.ts` вашего Angular приложения

```javascript
import { Component } from '@angular/core';
import { SwUpdate } from '@angular/service-worker';

@Component({
  selector: 'app-root',
  template: `
    <h1>Welcome to My PWA App</h1>
    <button *ngIf="showUpdateButton" (click)="updateApp()">Update App</button>
  `
})
export class AppComponent {
  showUpdateButton = false;

  constructor(private swUpdate: SwUpdate) {
    this.checkForUpdates();
  }

  checkForUpdates() {
    if (this.swUpdate.isEnabled) {
      this.swUpdate.available.subscribe(() => {
        this.showUpdateButton = true;
      });
    }
  }

  updateApp() {
    this.swUpdate.activateUpdate().then(() => document.location.reload());
  }
}
```

В данном примере:

- Мы импортируем `SwUpdate` из модуля `@angular/service-worker`.
- В конструкторе `AppComponent` мы проверяем, доступна ли функциональность обновления через Service Worker (`this.swUpdate.isEnabled`). Если доступно, мы подписываемся на событие `available`, которое срабатывает, к
огда новая версия приложения доступна для обновления.
- Когда событие `available` срабатывает, мы устанавливаем флаг `showUpdateButton` в значение `true`, чтобы отобразить кнопку обновления приложения.
- При нажатии на кнопку `Update App`, мы вызываем метод `updateApp()`, который активирует новую версию приложения через `this.swUpdate.activateUpdate()`. Затем происходит перезагрузка приложения с помощью `document.location.reload()`, чтобы применить обновление.

Обратите внимание, что для использования функциональности SW Update в Angular PWA приложении, вам необходимо настроить и зарегистрировать Service Worker с помощью Angular Service Worker модуля.

**Дополнительные материалы**

1) Документация и руководства по фреймворкам и технологиям

- https://angular.io/guide/service-worker-getting-started -  Angular Service Workers
- https://cli.vuejs.org/ru/core-plugins/pwa.html - Vue.js плагин PWA
https://developer.mozilla.org/ru/docs/Web/Progressive_web_apps - MDN документация PWA

2) Онлайн-курсы и обучающие материалы

- https://codelabs.developers.google.com/?text=pwa - PWA интерактивные курсы от Google
- https://web.dev/learn/pwa/
- https://dev.to/azure/welcome-to-30daysofpwa-2e54 - 30 дней PWA
- https://www.youtube.com/playlist?list=PLlrxD0HtieHjqO1pNqScMngrV7oFro-TY - PWA видеокурс для начинающих

3) Инструменты и библиотеки

- https://github.com/GoogleChrome/workbox - JS библиотека для построения прогрессивных веб приложений
- https://github.com/chrisdancee/react-ios-pwa-prompt - плашка для установки PWA приложения на ios (REACT)
- https://github.com/ProgressiveWebComponents/pwa-install - нативная плашка для установки

4) Сообщества и форумы разработчиков

- https://t.me/pwa_ru - русскоязычное сообщество PWA в Telegram
- https://progressive-web-apps.slack.com - глобальное сообщество PWA в Slack
- https://bit.ly/discord-pwa - глобальное сообщество PWA в Discord

5) Примеры и демонстрационные проекты

- Создаем PWA приложение с помощью React -  https://betterprogramming.pub/build-a-realtime-pwa-with-react-99e7b0fd3270
- Начало знакомства с Angular PWA -https://medium.com/ngconf/angular-pwa-install-and-configure-858dd8e9fb07

6) Онлайн-платформы и инструменты для развертывания и хостинга

Сначала мы пройдемся по сервисам, с помощью которых можно быстро развернуть фронтовую + бэковую часть приложения, а также базу данных. В дальнейшем по мере надобности и развития приложения, конечно, лучше переходить на собственный CI / CD через Docker на удаленный хостинг. Это позволит сэкономить денег, а также вы получите больше возможностей настройки и контроля над процессом.

Быстрый деплой:

- Firebase. С помощью firebase мы можем быстро захостить фронтовую часть нашего приложения. Ссылка на статью: https://medium.com/@rihanna.ke/how-to-quickly-deploy-your-progressive-web-apps-using-firebase-14a0c09e9a11
- Render. С помощью render.com мы можем задеплоить все части нашего приложения (фронт, бэк, бд). Сервис условно бесплатный и на первое время является отличным решением по сравнению с его популярным аналогом Heroku (из России пользоваться Heroku стало почти нереально из-за того, что для регистрации нужно указать банковскую карту). Ссылка на пример деплоя: https://www.youtube.com/watch?v=CVYFExfqEIw
- Amvera. amvera.ru/cloud является по сути русским аналогом Heroku и Render. На данный момент находится в активной разработке, но уже сейчас можно поучаствовать в бета тестировании.

Ручная настройка деплоя:

- Тут уже нужно настраивать свой CI / CD и конфигурировать удаленный хостинг. На первое время может быть избыточным решением, но в дальнейшем по мере развития приложения высока вероятность, что придется этим воспользоваться. Пример создания своего CI / CD для приложения: https://www.youtube.com/watch?v=fCQ8ogMHSoo