Angular и Service Worker (как создание PWA стало проще)

Как вам идея создать макcимально удобное для пользователей приложение, используя последние достижения технологий? По-моему, звучит заманчиво. И кто-то уже между прочим создал.

Называется такой вид приложения — PWA (Progressive web app).

Какое оно — PWA?

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

И что еще интереснее — плагин Lighthouse tool, с помощью которого мы можем проверить любой сайт на соответствие лучшим практикам. А потом играть в игру — увеличь показатели.

Впрочем, для начала достаточно пробежаться по базовому списку — наиболее важных вещей.

1. Используйте https протокол.

Зачем? Для обеспечение безопасности передачи данных. Подробнее by Google Why HTTPS Matters.   А еще без него не получится реализовать кучу плюшек через Service Worker, так как он не будет работать на HTTP сайтах.

2. Очевидно, что без  отзывчивого дизайна нам не обойтись.

3. С помощью кеширования (AppCache) благодаря Service Worker сайт должен работать оффлайн.

Поддержки пока нет в Edge и Safari. Но статус фичи и там и там в разработке. На сайте можно лицезреть текущую ситуацию.

Вообще про SW можно написать очень много, но это, пожалуй, вопрос отдельной статьи.

4. Юзер должен иметь возможность добавить приложение на главную страницу своего устройства, чтобы для повторного запуска не нужно было вводить снова запрос в браузере. Действительно, зачем нам лишние действия?

Намного круче было бы видеть на сайте кнопку с предложением установить его как приложение.

Для этого нужно добавить json файл Web App Manifest. С помощью его переменных можно определить вид иконки, название приложения, стартовый урл.

Также можно изменить стартовый экран, который появляется при запуске приложения до его загрузки.

По-умолчанию это белый лист, но мы можем добавить фон, надпись, изображение. Еще можно определить вид приложения: оно может отображаться как браузерное и как нативное.

Самыми важными свойствами файла манифеста можно считать те, что необходимы для появления баннера с предложением установить приложение на рабочий стол:

  • name (используется на баннере)
  • short_name (используется на домашнем экране) 
  • 192×192 png иконка (иконка должна содержать mime type of image/png)
  • start_url (с которого приложение будет запускаться)

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

Для этого в файл манифеста нужно вместо start_url добавить поле related_applications — объект с информацией о приложении. Подробнее

Текущую поддержку можно оценить тут.

5. Первая загрузка приложения должна быть быстрой даже в 3G сети. И реакция на действия пользователя должна для него ощущаться как быстрая, причем если для реакции на нажатие кнопки это 100ms, то  реакция приложения на скролл должна быть быстрее. Про все эти миллисекунды и фреймы анимации на google сайте.

6. Кросс-браузерность

7. Навигация по сайту не должна тормозить даже на медленной сети.

Решением проблемы является — SPA или так называемый skeleton screen — то есть юзеру показываются серые прямоугольники там, где еще не подгружены данные. И какой-то контент, например, заголовок. Это делает ожидание не таким утомительным.

8. В случае SPA нужно проверить, что роутер для любого урла может воссоздать соответствующее состояние приложения.

Создание Angular PWA с помощью service worker

С версии Angular-cli 1.6, которая на днях зарелизилась, мы можем автоматически создавать приложение с service worker.

А значит создание PWA теперь упрощается (Ура! Ура!).

Да и использовать Push Notifications из коробки — тоже круто.
Что ж, за дело!

Подтягиваем cli:

npm install @angular/cli@1.6 -g

Далее создаем приложение с service worker

ng new pwa —service-worker

Билдим с service-worker файлами

ng build —prod

Переходим в папку билда

cd dist

Так как ng serve не работает с service worker, то для тестирования SW локально нам необходимо воспользоваться реальным HTTP сервером с помощью http-server

npm install -g http-server

И наконец запускаем:

http-server -p 8080

Идем на http://localhost:8080/ 

В консоли хрома включаем режим Offline(вкладка Network), обновляем страницу и вуаля — видим, что все файлы закешировались, и наша страница работает оффлайн.

offline

Какие файлы кешировать и как — мы можем указать в файле ngsw-config.json.

Например, что добавлять в кэш сразу же (до того как юзер запросит), а что добавлять после запроса юзера. 

Подробнее в официальном руководстве.

А как обстоит дело с обновлением данных?

Проверим, сможет ли юзер получить обновленную версию приложения, несмотря на кэш.

Останавливаем http server, закрываем вкладку с приложением, но не окно браузера.

Далее вносим изменения в код приложения, билдим: ng build —prod и снова из папки dist запускаем:

cd dist

http-server -p 8080

Приложение откроется в предыдущем виде, так как sw берет данные из кэша, но если мы обновим страницу или откроем ее во второй раз, то увидим наши изменения.

На самом деле хотелось бы показывать обновленную версию при первой же загрузке.

И мы можем это сделать c помощью SwUpdate сервиса. В коде ниже мы подписываемся на обновление, и обновляем страницу, если они есть.

Таким образом, юзер получит свежую версию с первого открытия страницы.

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title = 'appUpdate';
  constructor(updates:  SwUpdate) {
    updates.available.subscribe((event) => {
        updates.activateUpdate().then(() => document.location.reload());

    });
  }
}

Как добавить Service Worker к существующему Angular приложению

Если у вас есть приложение, к которому вы хотите подключить функционал, реализующийся через service worker, то просто придется добавить самостоятельно все, что генерирует флаг —worker.

1. Добавляем пакет service-worker

npm install @angular/service-worker —save

2. Включаем поддержку подключения service worker при билдинге

ng set apps.0.serviceWorker=true

3. Импортируем и регистрируем Service Worker для prod режима

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';


import { ServiceWorkerModule } from '@angular/service-worker';
import { AppComponent } from './app.component';

import { environment } from '../environments/environment';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ServiceWorkerModule.register('/ngsw-worker.js',
 { enabled: environment.production })
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

4. Создаем файл ngsw-config.json. Он должен лежать в src.

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html"
      ],
      "versionedFiles": [
        "/*.bundle.css",
        "/*.bundle.js",
        "/*.chunk.js"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**"
      ]
    }
  }]
}

А далее запускаем все как и для сгенерированного автоматически приложения.

На этом на сегодня все. Дополнения и вопросы приветствуются!

Полезное

Статья о нововведениях в Angular 5.1 и Angular-cli 1.6
Про Service Worker в официальной Angular документации
Maxim Salnikov Automatic Progressive Web apps — видео с Angular Connect 2017
http://offlinefirst.org/
Maureen McElaney: Go Offline First to Save The World | JSConf EU 2017

Хотите быть в курсе новых статей?