Categories: Скрипты

Простое PWA приложение для сайта

Progressive web application (PWA) — прогрессивное веб-приложение, это технология для отображение сайта в отдельном приложении. Эту технологию развивает гугл, Apple еще не учитывает всех нюансов.

При запуске со смартфона на android высвечивается запрос на установку приложения в один клик. На рабочем столе появится ярлык для быстрого доступа к сайту, не нужно качать .арк файл, давать дополнительных разрешений. На iOs автоматического запроса нет (пока); установка происходит через — Расшарить — На экран «Домой». К тому же, iOs не всегда подтягивает иконку, название с manifest, кеширует меньше файлов.

Как сделать pwa для сайта

Если вкратце: создаем манифест, service-worker, ставим на сайт.

Manifest.json для pwa

Все файлы в принципе могут называться как угодно, просто так принято. Файл manifest:

{
 "short_name": "Bdseo.ru",
 "name": "Блог вебмастера",
 "icons": [
       {
     "src":"/images/beach.png",
     "sizes": "16x16",
     "type": "image/png"
   },
   {
     "src":"/images/beach.png",
     "sizes": "32x32",
     "type": "image/png"
   },
   {
     "src":"/images/beach.png",
     "sizes": "48x48",
     "type": "image/png"
   },
   {
     "src":"/images/beach.png",
     "sizes": "72x72",
     "type": "image/png"
   },
   {
     "src":"/images/beach.png",
     "sizes": "96x96",
     "type": "image/png"
   },
   {
     "src":"/images/beach.png",
     "sizes": "144x144",
     "type": "image/png"
   },
   {
     "src":"/images/beach.png",
     "sizes": "192x192",
     "type": "image/png"
   },
   {
     "src":"/images/beach.png",
     "sizes": "512x512",
     "type": "image/png"
   }
 ],

 "start_url": "/",
 "background_color": "#7ACCE5",
 "theme_color": "#7ACCE5",
 "orientation": "any",
 "display": "standalone"
}

short name — название на главном экране;
name — при запуске;
icons — массив с размерами; можно задать больше или меньше разрешений, можно разные иконки прописать;
start_url — какая страница сайта будет открываться;
orientation — можно задать только горизонтальную, вертикальную или в любом положении экрана;
display — standalone, как отдельное приложение, со статус баром. Можно задать еще 3 варианта: Fullscreen (на весь экран, без статус бара), Minimal-UI (будет строка с url и кнопкой Меню как в браузере), Browser (как в браузере).

Остальное цвета. Это не все функции, для примера.

Service-worker файл для pwa

Файл-обработчик самого приложения.

var doCache = true;

// Имя кэша
var CACHE_NAME = 'pwa-from-bdseo';

// Очищает старый кэш
self.addEventListener('activate', event => {
   const cacheWhitelist = [CACHE_NAME];
   event.waitUntil(
       caches.keys()
           .then(keyList =>
               Promise.all(keyList.map(key => {
                   if (!cacheWhitelist.includes(key)) {
                       console.log('Deleting cache: ' + key)
                       return caches.delete(key);
                   }
               }))
           )
   );
});

// 'install' вызывается, как только пользователь впервые открывает PWA 
self.addEventListener('install', function(event) {
   if (doCache) {
       event.waitUntil(
           caches.open(CACHE_NAME)
               .then(function(cache) {
                   // Получаем данные из манифеста (они кэшируются)
                   fetch('/manifest.json')
                       .then(response => {
                           response.json()
                       })
                       .then(assets => {
                       // Открываем и кэшируем нужные страницы и файлы
                           const urlsToCache = [
                               '/app/',
                               '/static/core/logo.svg*',
                           ]
                           cache.addAll(urlsToCache)
                           console.log('cached');
                       })
               })
       );
   }
});

// Когда приложение запущено, сервис-воркер перехватывает запросы и отвечает на них данными из кэша, если они есть
self.addEventListener('fetch', function(event) {
   if (doCache) {
       event.respondWith(
           caches.match(event.request).then(function(response) {
               return response || fetch(event.request);
           })
       );
   }
});

Задаем путь к manifest.json, кешируем или нет и что кешируем. Внимательно проверяйте пути к файлам.

Установка файлов на сайт для pwa

Дальше задаем путь к файлам на нужных страницах. При использовании движков достаточно задать в header, footer коде.

<link rel="manifest" href="/manifest.json">

Путь к файлу manifest, размещаем в заголовке.

<script>
       if ('serviceWorker' in navigator) {
           window.addEventListener('load', function() {
               navigator.serviceWorker.register('/service-worker.js').then(function(registration) {
                   // Registration was successful
               console.log('ServiceWorker registration successful with scope: ', registration.scope);
             }, function(err) {
               // registration failed   
               console.log('ServiceWorker registration failed: ', err);
             }).catch(function(err) {
               console.log(err)
             });
           });
         } else {
           console.log('service worker is not supported');
         }
   </script>

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

Также однотипные файлы/скрипты можно объединять для оптимизации. Например, у вас все js-скрипты в одном файле — подключите и этот. Все json в отдельной папке — положите манифест туда.

В этом примере будет стандартный запрос. Если пользователь отказался, запрашивать какое-то время не будет.

Также можно использовать нестандартную форму запроса, «отлавливать» установил пользователь приложение или нет. Еще высвечивать инструкцию если пользователь зашел с айфона. По нестандартной форме запроса, например через поп-ап окно, я напишу позже.

veniamin

View Comments

  • Ура. Я все смог сделать. У меня теперь PWA в ядре framework. Сначала думал статью про это написать, потом решил что нафига я буду конкурентам рассказывать как это работает. У меня теперь все сайты, которые берут дистрибутив с PWA работают и на рабочий стол добавляются.  На Java - это же вообще говнище. Они там теребонькают три месяца чтобы какашку задеплоить в Google Play и делают это с каждым сайтом. Сраное извращение меня не коснулось. Спасибо дружище, но мне пришлось еще 5 манов прочитать. Жду от тебя новых статей.

    • Всегда пожалуйста. Спасибо за обратную связь.
      По ява согласен и нет: парится надо, но когда есть опыт и набитые шишки - все делается красиво и быстро.
      У меня даже под беттинг, гемблинг прилы отлично работают, некоторые в маркете.
      "Обычные" сайты вообще без проблем. Приложение делаю сейчас за ~20 минут.

  • Кароче. Install вообще не обязателен как я понял. А у тебя кэш сторадж пустое. Проверь сам. Воркер регистрируется, а кэша в хранилище нету. Мой воркер тоже не работает в том числе и с мобильного устройства. Если выполнить добавление кэша из обычных скриптов - в хранилище появляются записи, но дерьмо в том, что они видимо не возвращаются из кэша. Это говно нельзя использовать - нужно писать APP нормальное без строки URL.

    • В блоге описал самый простой пример. Если он не работает - напишите (проверял на 2 сайтах)
      Вообще, у меня есть 4 или 5 вариантов PWA, с разными способами вызова, кеширования, service-worker, вызов для iOs). Но они для коммерческих проектов.

  • В общем я сделал немного по другому потому что воркер не кэширует. На каждую загрузку нужно выполнить:

     if('caches' in window) {
    
      caches.open('RevolveR_Cache').then(
    
       function(cache) {
    
        cache.add(document.location.pathname);
    
        cache.keys().then(function(cachedRequests) {
    
         //console.log(cachedRequests); // [Request, Request]
    
        });
    
       }
    
      );
    
      if ('serviceWorker' in navigator) {
    
       window.addEventListener('load', function() {
    
        navigator.serviceWorker.register('/Interface/worker.js?revolverv.1.0.3').then(
    
         function(registration) {
    
          console.log('ServiceWorker registration successful with scope: ', registration.scope);
    
         },
         function(err) {
    
          console.log('ServiceWorker registration failed: ', err);
    
        }).catch(
    
         function(err) {
    
          console.log(err);
    
        });
    
       });
    
      } 
      else {
    
       console.log('service worker is not supported');
    
      }
    
     }

     

    Воркер я сделал вот такой:

     

    const CACHE_NAME = 'RevolveR_Cache';
    
    self.addEventListener('activate', evt => {
    
      evt.waitUntil(
    
        caches.keys().then(keys => {
    
          return Promise.all(
    
            keys.filter(key => key !== CACHE_NAME).map(key => caches.delete(key))
    
          );
    
        })
    
      );
    
    });
    
    self.addEventListener('install', function(event) {
    
       event.waitUntil(
    
         caches.open(CACHE_NAME).then(
    
          function(cache) {
    
           fetch('/manifest/').then(response => {
    
                   response.json();
    
               }).then(assets => {
    
                console.log('cached');
    
               })
    
             })
    
       );
    
    });
    
    self.addEventListener('fetch', evt => {
    
      evt.respondWith(
    
        caches.match(evt.request).then(cacheRes => {
    
          return cacheRes || fetch(evt.request).then(fetchRes => {
    
            return caches.open(CACHE_NAME).then(cache => {
    
              cache.put(evt.request.url, fetchRes.clone());
    
              return fetchRes;
    
            })
    
          });
    
        })
    
      );
    
    });
    

    Воркер работает фигово. Он должен добавлять ресурсы автоматически но пришлось это сделать кодом выше. Не знаю вообще кэширование возвращается или нет. Lighthouse говорит что оно херовенько работает. Вручную добавлять неинтересно, это будет максимум CSS иконки и шрифты, а все страницы дтнамического сайта можно добавить только при вызовах загрузки, а не из воркера.

     

     

    • И еще нужно учитывать, что максимальный кеш PWA ~50 мбайт

  • Фиг его знает как оно работает. В кэш я добавление сделал. У меня весь сайт на Fetch запросах. Оно в хранилище кэша есть. Это точно перехаватывает? Я чего-то не смог логирование сделать выброса актуального кэша.

Recent Posts

Бонус 100 USDT +10 BUSD от Binance

Биржа криптовалют Binance проводит сейчас промо-акцию: новым пользователям дают ваучеры в сумме 110 долларов. Деньги…

2 года ago

Как парсить длительность видео youtube на php в привычном виде

Самый главный момент в работе с youtube - это получить ключ api через консоль разработчика…

2 года ago

Как удалить чужую сессию пользователя в ubuntu (linux)

Арендую сервер для небольшого проекта на python. И вот приходит мне уведомление, что за сутки…

2 года ago

Как наложить watermark на видео в python windows массово

Тестирую одну схему, и нужно на много видео наложить watermark. Решил делать через Python 3,…

3 года ago

Kwork.ru: опыт поиска исполнителя и поздравление

Пришла в голову одна интересная идея. Связанно с тиктоком. Решил поискать исполнителя, который будет монтировать…

3 года ago

Отзыв о Накрутке подписчиков instagram через Socpublic в автоматическом режиме

Решил проверить "автоматическую" накрутку подписчиков в инстаграмме через сервис активной рекламы Socpublic.com. Сразу скажу -…

3 года ago