Как заставить блог Jekyll работать в автономном режиме с помощью Service Workers

Опубликовано: 2017-01-26

Short Bytes: Знаете ли вы, что с появлением Service Workers можно заставить веб-сайты работать в автономном режиме! Такие веб-приложения называются PWA (Progressive Web Apps). В этом практическом руководстве я собираюсь помочь вам использовать сервисного работника, чтобы заставить блог/веб-сайт на основе Jekyll работать в автономном режиме, а также некоторые интересные вещи, которые с ним связаны.

(ПРИМЕЧАНИЕ . Фрагменты кода в статье взяты из репозитория кода моего блога. При необходимости на него можно ссылаться. Если вы новичок в Jekyll, вы можете прочитать 3-ю серию статей о хитростях CSS.)

ЗАДНИЙ ПЛАН

Ранее существовал кеш приложений на основе файла YAML, который был очень жестко закодирован по своей природе и не мог использоваться для динамического кэширования ресурсов и веб-страниц. Входите, сервисные работники. Простой Javascript API на основе простых событий для динамического кэширования сервис-воркеров для хранения ресурсов, чтобы их можно было использовать для обслуживания веб-страниц при отсутствии сети.

Сервисные работники появились в Chrome Canary в 2014 году, но его спецификация все еще пересматривается/дополняется и разрабатывается. В 2015 и 2016 годах команда Google Chrome активно распространяла информацию об этой новой технологии в браузерах. Только Apple не поддерживает это (даже на момент написания этой статьи) на своих устройствах (по неизвестным причинам) [они также не принимают активного участия в каких-либо обсуждениях спецификаций сервис-воркеров].

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

Service Worker позволяет нам кэшировать (хранить в течение длительного времени) активы, такие как JavaScript, CSS, HTML, изображения, файлы шрифтов в кеше сервисного работника браузера, поэтому в следующий раз, когда пользователь загружает эту страницу, она загружается почти мгновенно. . А также, поскольку в этой стратегии кэширования браузер ищет доступность ресурсов сначала из кеша сервис-воркера, веб-страница обслуживается, даже когда она не в сети! Если какого-либо актива нет в кеше, то для его извлечения отправляется сетевой запрос.

Сервисный работник также включает push-уведомления, которые в наши дни можно увидеть на многих веб-сайтах, включая Facebook, Whatsapp в Интернете и Twitter. В первую очередь мы будем говорить об автономной функции. Это практическое руководство относится к Jekyll, однако большую часть кода сервис-воркера можно применить к любому веб-сайту.

Поскольку Jekyll обслуживает статическое содержимое ( это генератор статических сайтов, да! ), код нашего сервис-воркера будет очень простым и простым для понимания.

ДАВАЙТЕ ПРОКАЧАТЬ:

На всех соответствующих страницах выполняется следующий фрагмент скрипта. Он делает следующие вещи:

  1. Проверка наличия API сервис-воркера в браузере и регистрация сервис-воркера.
  2. Когда сервис-воркер будет активирован, поместите пользователю приятное сообщение о том, что веб-сайт готов к использованию в автономном режиме.
 функция showOfflineToast() {
  let offlineToast = document.querySelector('.offline-ready');
  offlineToast.classList.add('активный');
  setTimeout (функция () { 
    offlineToast.className = offlineToast.className.replace("active", "").trim();
  }, 5500);
}

// (1)
если (navigator.serviceWorker) {
  navigator.serviceWorker.register('/sw.js').then(function(reg) {
      если (!reg.installing) вернуться;
      console.log("[*] ServiceWorker устанавливается...");

      var worker = reg.installing;

      worker.addEventListener («изменение состояния», функция () {
          если (worker.state == 'избыточный') {
              console.log('[*] Ошибка установки');
          }
          если (worker.state == 'установлено') {
              console.log('[*] Установка выполнена успешно!');
          }
          // (2)
          if (worker.state == 'активировано' && !navigator.serviceWorker.controller) {
            показатьOfflineToast();
          }
      });
  });
} 

gdad-s-river.github.io-(iPhone 6)

Вы можете добавить этот фрагмент кода в файл, скажем, serviceWorker.html внутри каталога include вашего кода Jekyll и включить его в default.html , используя жидкий механизм шаблонов Jekyll.

 <!ДОКТИП HTML>
<html>

  {% включает head.html %}

  <тело>
    {% включает заголовок.html %}

    <div class="контент страницы">
      <div класс="обертка">
        {{ содержание }}
      </div>
    </div>

    {% включает footer.html %}

    <!-- Содержит указанный выше код в теге script-->
    {% включает serviceWorker.html %} 

    <div class="offline-ready">Сайт готов к работе в автономном режиме</div>
  </тело>

</html>

Теперь к реальному коду сервис-воркера, который творит чудеса. Этот код находится в sw.js в корне вашего кода Jekyll.

 //sw.js
---
макет: ноль
---

const staticCacheName = "gdad-s-river-static-v61";

console.log("установка сервис-воркера");

константные файлыToCache = [
  "/",
  {% для страницы в site.html_pages %}
    '{{ page.url }}',
  {% конец для %}
  {% для сообщения в site.posts %}
    '{{ post.url }}',
  {% конец для %}

  // может быть автоматическим, а не ручным вводом
  "/assets/images/bhavri-github-callbacks.png",
  "/assets/images/bhavri-github-issues.png",
  "/assets/images/jakethecake-svg-line-anime.png",
  "/assets/images/svg-animated-mast-text-shapes-tweet.png",
  "CSS/основной.CSS",
  "/о/",
  "/index.html"
];

staticCacheName — это версия кеша, которая должна обновляться каждый раз, когда я вношу некоторые изменения в кешированные ответы (например, я вношу изменения, скажем, в файл CSS или сообщение в блоге). И я просто определяю, какие запросы я хочу перехватывать и кэшировать в массиве (используется в следующем фрагменте).

 //sw.js

self.addEventListener ("установить", функция (е) {
  self.skipWaiting();
  e.waitUntil(
    caches.open(staticCacheName).then(function(cache){
      вернуть cache.addAll (filesToCache);
    })
  )
});

self.skipWaiting означает, что каждый раз, когда этот файл sw.js изменяется, более новая версия сервисного работника не должна ставиться в очередь, а должна немедленно становиться активной (можно запросить у пользователя запрос на обновление страницы с сообщением вроде Веб-страница была обновлена ​​/ изменена, нажмите «Обновить», чтобы загрузить новые сообщения или что-то еще. ), выбрасывая старую версию.

Java-and-android-square-ad-1

e.waitUntil цитата с веб-сайта MDN:

«Метод ExtendableEvent.waitUntil() продлевает время жизни события. В сервис-воркерах продление жизни события не позволяет браузеру завершить сервис-воркер до завершения асинхронных операций внутри события».

Я открываю кеш с именем gdad-s-river-static-v61 , который возвращает промис с именем моего кеша, а затем я вызываю cache.addAll (который использует API выборки в фоновом режиме), который извлекает все запросы в предоставленный массив и кэширует их.

К следующему фрагменту!

 //sw.js

self.addEventListener («активировать», function (e) {
  e.waitUntil(
    caches.keys().then(function(cacheNames){
      вернуть Обещание.все(
        cacheNames.filter (функция (cacheName) {
          return cacheName.startsWith("gdad-s-river-static-")
            && cacheName != staticCacheName;
        }).карта(функция(названиекэша){
          вернуть cache.delete(cacheName);
        })
      )SS
    })
  )
});

Когда сервис-воркер активируется, я гарантирую, что любой сервис-воркер, версия которого не является последней, будет удалена. Например, если моя последняя версия кеша, скажем, gdad-s-river-static-v61 , а кто-то все еще использует gdad-s-river-static-v58 , при его/ее следующем посещении я хочу, чтобы этот клиент не заботился о загружая одну версию за раз, но сразу же удаляйте эту версию, чтобы установить последнюю.

 //sw.js

self.addEventListener («выборка», функция (е) {
  e.respondWith(
     caches.match(e.request).then(function(response) {
       вернуть ответ || выборка (электронный запрос);
     })
   )
});

В событии выборки я просто говорю сервисному работнику, как реагировать на конкретный сделанный запрос (поскольку мы перехватываем полномочия, дающие ответ, сервисные работники работают только на защищенных веб-сайтах, известных как исходные https). Я говорю ему сопоставить запрос с теми, которые кэшируются в браузере, и, если он не находит этот конкретный ответ на запрос, получить его через сеть, иначе обработать его из кэша.

Тада! Сервисный работник перевел блог на базе Jekyll в автономный режим!

СЮРПРИЗ! КРУТАЯ ВЕЩЬ:

Облом: это не будет работать на устройствах iOS.

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

 {
  "name": "гдад-с-река",
  "short_name": "гдад-с-река",
  "theme_color": "#2196f3",
  "background_color": "#2196f3",
  "дисплей": "автономный",
  "Объем": "/",
  "start_url": "/",
  "значки": [
    {
     "src": "активы/изображения/favicon_images/android-icon-36x36.png",
     "размеры": "36x36",
     "тип": "изображение\/png",
     "плотность": "0,75"
    },
    {
     "src": "активы/изображения/favicon_images/android-icon-48x48.png",
     "размеры": "48x48",
     "тип": "изображение\/png",
     "плотность": "1.0"
    },
    {
     "src": "активы/изображения/favicon_images/android-icon-72x72.png",
     "размеры": "72x72",
     "тип": "изображение\/png",
     "плотность": "1,5"
    },
    {
     "src": "активы/изображения/favicon_images/android-icon-96x96.png",
     "размеры": "96x96",
     "тип": "изображение\/png",
     "плотность": "2.0"
    },
    {
     "src": "активы/изображения/favicon_images/android-icon-144x144.png",
     "размеры": "144x144",
     "тип": "изображение\/png",
     "плотность": "3.0"
    },
    {
     "src": "активы/изображения/favicon_images/android-icon-192x192.png",
     "размеры": "192x192",
     "тип": "изображение\/png",
     "плотность": "4,0"
    }
  ]
}

и добавьте его в файл head.html внутри тега head,

 <голова>
 <!-- кое-что -->
	<link rel="manifest" href="/manifest.json">
 <!-- кое-что -->
</голова>

Затем, при втором посещении вашего веб-сайта (в течение 5 минут), пользователю будет предложено добавить ваш веб-сайт на главный экран (чтобы он отображался со значком, как и в других нативных приложениях), с которым вы будете работать так же, как приложение.

Скриншот_20170123-232947

РЕСУРСЫ

  • Подробную информацию об автономных функциях сервис-воркера и стратегиях кэширования можно найти в оффлайн-поваренной книге этого замечательного Джейка Арчибальда.
  • Очень подробный бесплатный курс Udacity обо всем, что вам нужно знать о сервис-воркерах и IndexDB.

Считаете ли вы эту статью в блоге Jekyll интересной и полезной? Не забывайте делиться своими мнениями и отзывами.

Читайте также : Ecosia — поисковая система, которая сажает деревья