«Задеплоил сервис-воркер — нужно покупать новый домен», — известная шутка о том, как сложно писать собственную логику кеширования. С приходом шестой версии библиотеки Workbox для прогрессивных веб-приложений (PWA) больше не нужен компромисс между гибкостью и удобством автоматизации сетевых задач. Максим Сальников рассказал, как начать работу с Workbox 6, реализовать типовую функциональность для офлайнового веб-приложения и пойти дальше, добавив собственную логику кеширования.
От докладчика:
— Здравствуйте, уважаемые веб-разработчики, привет, любители фронтенда. Если описать мой сегодняшний доклад самыми общими словами и уместить это описание в одно предложение, то он о том, как сделать наши фронтенд-приложения быстрее и удобнее для наших уважаемых пользователей и как самим разработчикам при этом получать удовольствие от процесса разработки.
Меня зовут Максим Сальников, я отвечаю за успех облачных разработчиков в компании Microsoft, и я большой любитель технических сообществ. Я организовываю митапы, конференции и воркшопы. Вы можете увидеть меня как докладчика на русскоязычных и англоязычных конференциях, посвященных вебу и прогрессивным веб-приложениям в частности.
Сегодня обсудим с вами, что происходит в мире PWA на данный момент, посвятим основную массу слайдов и времени доклада сервис-воркеру, а именно его автоматизации. Также я поделюсь ссылками на ресурсы, где можно продолжить общение на русском языке по этой тематике.
Что сегодня происходит с прогрессивными веб-приложениями? Американские горки — какие-то новости радуют, какие-то не очень.
Например, компания Mozilla анонсировала, что в следующей версии Firefox функциональность PWA поддерживаться не будет. Немного кликбейтный заголовок, обозначающий то, что компания остановила разработку той части PWA, которая отвечает за установку веб-приложения на устройство. Но это толком там и не работало, было всегда скрыто за флагом, так что это не такая уж большая новость. К счастью, всё, что касается API сервис-воркера, остается, и разработка продолжается.
Компания Google радует — теперь прогрессивные веб-приложения можно монетизировать, используя API для продажи цифровых товаров на их площадке Google Play. Для этого, правда, придется PWA обернуть в нативную оболочку мобильного приложения. К счастью, сделать это можно легко, используя инструмент от той же компании Google — Trusted Web Activity, TWA.
Компания Apple на своей конференции для разработчиков анонсировала, что 16 API, связанных с доступом к аппаратным возможностям устройств, в ближайшее время не будут реализованы в WebKit (и соответственно, в Safari), потому что по наличию или отсутствию этих API и их возможностей можно составить цифровой профиль пользователя и тем самым нарушить его приватность.
Хорошие новости от компании Microsoft. Инструмент PWA Builder, позволяющий создавать дистрибутивы, которые мы можем загружать в магазины приложений, живет и развивается. И всё проще и проще становится отправлять наши прогрессивные веб-приложения в натуральном виде в магазин приложений Microsoft Store.
Когда смотришь на подобные заголовки, складывается ощущение, что веб форкнули — какие-то компании ушли в сторону приватности, при этом страдает функциональность. Какие-то, наоборот, ушли в сторону функциональности — при этом, возможно, страдает приватность.
Ссылка со слайда
Что делать нам, разработчикам, как разрабатывать современные веб-приложения? Ответ — давайте следовать веб-стандартам. Все API, которые мы с вами будем сегодня рассматривать — часть веб-стандартов или, как минимум, черновики. То есть они прошли все необходимые обсуждения, слушания, все формальные процедуры, чтобы стать тем, что потенциально может стать веб-стандартом, если он сейчас в статусе черновика.
Технически прогрессивные улучшения или, как механизм для этого, feature detection — то, что нам известно в мире фронтенда с незапамятных времен.
Ссылки со слайда: первая, вторая
Как понять все эти термины? PWA — что это, как это связано с сервис-воркером, что включает в себя сервис-воркер? Я сделал простую диаграмму, чтобы задать контекст нашей сегодняшней дискуссии. Под идеей PWA понимаются два концепта, связанных с веб-приложениями: возможность их установки на устройства пользователей и интересные возможности через набор новых web-API.
Все эти возможности используются через сервис-воркер, который служит основной частью того, что мы называем идеей PWA, но PWA — это не только сервис-воркер. Если мы копнем поглубже, то обнаружим, что сервис-воркер API — это целое семейство API, множество методов, и большинство из них так или иначе связано с работой с сетевыми запросами. И именно на этом уровне работает наш, сегодня пока еще не названный, герой.
Из многообразия этого подуровня API что-то связано с кешированием, но не все.
Ссылка со слайда
Если вам нужна мотивация в плане количественных показателей популярности сервис-воркеров — 1% из выборки сайтов, которые находятся в HTTP Archive, используют сервис-воркеры. Рост заметен, не взрывной на текущий момент времени, но и останавливаться он не планирует.
Ссылка со слайда
Может быть, следующая цифра вас воодушевит больше. 1% тех самых страниц под управлением сервис-воркеров обеспечивает почти пятую часть веб-трафика, что говорит о том, что в этот 1% страниц входят популярные и часто посещаемые ресурсы, то есть достаточно известные.
Почему наблюдается такая популярность сервис-воркеров именно со стороны известных веб-ресурсов?
Удобство для пользователей, все сводится к этому. Возвратимся к главному слогану нашего доклада — удобные и быстрые приложения.
При этом мы оставляем всю природу и силу веба, если мы используем именно веб-технологии — общедоступность, простоту обмена ссылками и открытость платформы.
Если все это так удобно для пользователей, почему каждое приложение не использует сервис-воркер?
Ссылка со слайда
Не все так просто с точки зрения разработчиков. Шутка из 2019 года все еще имеет под собой основания. Я вольно ее перевел и возьму смелость нарушить идею о том, что хорошая шутка в объяснении не нуждается — все же объясню, что тут имеется в виду.
Ссылка со слайда
Дело в том, что в теории работа с сервис-воркером выглядит достаточно просто. Что такое сервис-воркер? Во-первых, это JavaScript-код. Во-вторых, это код, который исполняется в отдельном контексте относительно основного кода нашего приложения. В-третьих, это код, который исполняется только как ответ на какие-то события (events).
Вот три базовых события, которые позволяют нам сделать, допустим, офлайн-версию самого приложения или программной оболочки или application shell.
Событие install — кладем нужные ресурсы в кеш: index.html, главный бандл JavaScript, главный бандл CSS, может быть, что-то еще.
Ссылка со слайда
Событие activate — управляем версиями, если приложение обновилось.
Ссылка со слайда
Событие fetch — тут мы немного обманываем основное приложение тем, что в ответ на все явные и неявные HTTP, a точнее HTTPS-запросы мы можем выдавать данные не из интернета, а те, что мы до этого закешировали. Это в теории.
Ссылка со слайда
В руководстве вы найдете примерно одинаковые куски кода, примерно в сотню строчек. (Я показываю этот самый кусочек кода исключительно для демонстрации объема.) Найдете наивную реализацию того, что можно назвать офлайн-приложением. Наивную и не готовую для жизни в production, потому что не хватает достаточно важных вещей — автоматизации, настроек, расширяемости.
Действительно, если мы говорим не о приложении «Hello, World!», а о том, которое растет, меняет список ресурсов — ведь даже те ресурсы, что у нас есть, могут добавлять в свои названия хеш-суммы, чтобы как-то работать с http-кешированием. Все это нужно предусмотреть.
Забота о пользователе: если мы что-то кешируем, то должны убедиться, что это умное кеширование, что мы не скачиваем байты данных, которые нам не нужно скачивать, если этот ресурс не обновился. В этом наборе строчек мы точно не поместим весь набор нужных фолбэков, а они нам понадобится в вебе как в среде исполнения нашего приложения.
Это зоопарк всех возможных сценариев, платформ, браузеров, типов подключений. Кроме того, мы не получим удовольствие как разработчики — все-таки мы хотим иметь полный контроль над тем, что мы разрабатываем, нужен серьезный подход к тестированию и отладке.
Ссылка со слайда
Даже если мы сделаем все эти вещи, а это уже будет не сотня строк, а на порядок больше, то приложение все еще не готово для production, потому что мы наверняка что-то из этого нового расширенного списка забыли. В итоге мы придем к той самой шутке про необходимость нового домена, потому что версия почему-то зависла.
Ссылка со слайда
Именно поэтому, если мы посмотрим на статистику HTTP Archive, примерно треть всех текущих сервис-воркеров в выборке адресов сделаны с помощью Workbox или его предков. Вот мой личный топ особенностей этой библиотеки, из-за которых мне она так нравится:
Я надеюсь, что убедил вас попробовать. Давайте сделаем это незамедлительно.
Помните тот самый демонстративный кусок кода, несколько десятков строчек? В Workbox это будет одна строчка — вызов одного конкретного метода, который называется precacheAndRoute. Его название говорит само за себя: Workbox, закешируй этот набор ресурсов и настрой роутинг, чтобы эти ресурсы выдавались из кеша, если это возможно. Как параметр этому методу мы передаем массив, содержащий конкретный список ресурсов.
Чтобы заменить эту переменную, которая исполняет роль плейсхолдера в исходном сервис-воркере, и полностью автоматизировать процесс подготовки сервис-воркера, нам нужно сделать несколько шагов.
В первую очередь — заполнить эту переменную конкретным списком файлов (и их хеш-сумм), которые нам необходимо закешировать.
Нативные импорты JavaScript в сервис-воркерах пока еще не работают, поэтому сервис-воркер будет необходимо собрать.
В конце концов нужно сообщить приложению, что теперь оно работает под управлением сервис-воркера.
При этом первые пару пунктов неплохо бы делать при каждом билде приложения. Давайте приступим к этим шагам незамедлительно. Для этого нам потребуется установить модуль workbox-build, который нам поможет с пунктом номер один.
Это модуль для Node, соответственно добавим немного JavaScript-кода.
В конфигурации мы укажем тот самый исходный сервис-воркер и адрес итогового сервис-воркера.
Самое главное — мы должны объяснить Workbox, какие именно файлы составляют ту самую программную оболочку, тот самый application shell. К счастью, это делается очень удобным методом glob-шаблонов. Я гарантирую, что вы сможете настроить необходимую выборку ресурсов для вашего даже сложного по конфигурации веб-приложения. В этом конфиге есть много других свойств, которые позволяют вам совершенно точно затюнинговать этот процесс.
Вызов метода injectManifest с говорящим названием.
Это позволит нам внедрить массив, который Workbox для нас собрал на основе шаблонов, вместо переменной, которая исполняет роль плейсхолдера. В итоге у нас получится примерно такого вида сервис-воркер с одним-единственным методом precacheAndRoute.
Следующий шаг — бандлинг. Заодно сделаем минификацию, чтобы следовать всем идеям современной веб-разработки. Можете использовать свой любимый инструмент сборки, в моем случае это Rollup.
В общем случае нам понадобятся три плагина.
Ссылка со слайда
Как их настроить, можно посмотреть на этом слайде. Базовая настройка требуется только в плагине rollup-replace, который позволяет выбирать режим Workbox, development или production, заменой строки в исходном коде Workbox.
Чем отличаются режимы? В режиме production вся отладочная информация будет полностью исключена, в режиме development вы увидите детальный лог в консоли браузера, который позволяет точно прослеживать, что именно делает Workbox. Очень удобно.
Terser сделает минификацию, чтобы получить примерно такой вид итогового сервис-воркера.
Даже не пытайтесь понять, что здесь происходит, этот код не для человека, а для машин — а именно для браузеров. Хочу только заметить, что при каждом очередном билде нашего приложения итоговый файл сервис-воркера будет отличаться от предыдущего хотя бы потому, что мы туда внедряем хеш-суммы тех ресурсов, которые просим закешировать. Это важно для понимания того, как работает механизм обновления версий в Workbox.
Осталось интегрировать сборку сервис-воркера в общий билд приложения.
Ссылка со слайда
Последний шаг из нашего набора — регистрация в приложении. Тут можно пойти путем вызова нативных методов, метод register для объекта сервис-воркер, а можно опять обратиться за помощью к нашему герою — Workbox.
С использованием модуля workbox-window у нас есть удобный метод для регистрации — на самом деле это синтаксический сахар для нативного метода, плюс там сразу внедрена лучшая практика по моменту регистрации сервис-воркера, а именно в событии window.onload. Чтобы не конкурировать за сетевые и процессорные ресурсы с основным потоком JavaScript, мы откладываем регистрацию сервис-воркера настолько, насколько это возможно.
Кроме того, становится доступен удобный механизм для показа вопроса про обновление версии — я называю это «вежливым обновлением».
Вероятно, при серфинге в вебе вы видели диалог, возникающий на некоторых сайтах, который спрашивает: не хотите ли вы обновить страничку для работы с ее новой версией? Что это значит? Во-первых, этот сайт находится под управлением сервис-воркера. Во-вторых, то, что вы сейчас видите на экране, было извлечено из кеша в вашем устройстве и, скорее всего, это доступно и полностью офлайн. В-третьих, на сервере находится обновленная версия, поэтому сервис-воркер дает сигнал приложению спросить, не хотите ли вы эту новую версию получить — и вы сами решаете, да или нет.
Допустим, если вы начали заполнять большую форму, и через секунду прилетело это сообщение, то, может быть, вы откажетесь, потому что все данные могут быть потеряны. Тут мы возвращаемся к хорошему опыту пользователя — к вежливому процессу обновления.
Исходный код именно для этой части сервис-воркера есть в репозитории по адресу aka.ms/workbox6. Там находится код сегодняшнего демонстрационного приложения и ссылка на его онлайн-версию, чтобы вы могли с ним поиграть и посмотреть, какие процессы там происходят. Открывайте DevTools, вкладку Application, что я и сделаю прямо сейчас.
Итак, приложение — простой блог, сделаем его офлайн-готовым, то есть работающим вне зависимости от подключения к сети. Давайте посмотрим, как это выглядит.
Обратите внимание на правую нижнюю часть — Workbox нам выдал все подробные детали того, что он закешировал при первой загрузке приложения. Уходим в режим офлайн, обновляем страничку — программная оболочка работает, потому что файлы извлекаются уже не из сети с массой сетевых ошибок, потому что мы в режиме офлайн, а из кеша.
При этом мы, конечно, потеряли потребляемые данные — те статьи, которые были на главной странице, потому что они уже загружались в рантайм. Это мы тоже исправим.
Что мы в итоге получили? Полностью работающую офлайн-оболочка приложения, управление версиями со стороны Workbox и детализированную информацию для разработчиков.
Как я обещал, давайте исправим рантайм-кеширование, чтобы и статьи тоже при их первой загрузке аккуратно складывались в кеш для дальнейшей работы в офлайне.
Посмотрим на исходный сервис-воркер. Все начинается с импортов, конкретных методов, которые нам нужны. Помните пользовательский опыт? Никакого лишнего, мертвого кода.
Если мы в блоге используем аватары из сервиса Gravatar, для этого мы можем настроить самую консервативную стратегию — всегда брать их из кеша, если они там доступны с предыдущей загрузки. Как вы видите, этот метод очень декларативен, то есть это выглядит как настройка роутинга. Для адресов, который попадают под этот шаблон, в данном случае я его задаю через RegExp, мы просим Workbox использовать стратегию Cache First.
Если речь идет про другие типы информации, которые приложение загружает в процессе использования, например, про список статей, то тут больше подходит стратегия Network First. Список статей может обновляться достаточно часто, особенно если мы делаем новостной ресурс. Там всегда есть смысл попробовать сеть: если сервер доступен, то мы всегда будем загружать свежую информацию, если нет, возьмем из кеша, а еще можно об этом уведомить пользователя.
Самая интересная стратегия предлагается для конкретной статьи или конкретного поста. Называется Stale While Revalidate, и говорит она следующее: Workbox, попробуй взять данные для этого адреса из кеша, если они там есть, и отправь их в приложение, чтобы оно их мгновенно показало. В это же самое время сходи и посмотри, есть ли по этому адресу в сети обновление. Если есть — загрузи и положи его в кеш для следующего использования.
В то же время в моем примере кода вы можете увидеть, что используется плагин Broadcast Update, который дает нам возможность отправить сообщение приложению. Если данные обновились, можно спросить пользователя: «Не желаете ли получить обновленную статью?»
Есть множество готовых для использования стратегий и хороший набор плагинов, который позволяет нам эти стратегии тюнинговать, — уже встроенные в Workbox.
Ссылка со слайда
Перейдя на следующий уровень абстракции, мы в версии шесть Workbox обнаружим такой концепт, как рецепты, которые позволяют еще проще настраивать, например, рантайм-кеширование.
Если мы всегда знаем, что сам шрифт с Google-серверов и CSS к нему доступны по таким-то адресам, и к ним всегда подходит одна и та же стратегия — можно реализовать это буквально одной строчкой. Если нужно, мы можем это каким-то образом настроить. В моем примере я задал свое имя кешу, который будет в браузере.
Ссылка со слайда
Аналогично с картинками. Есть хорошие практики для динамического кеширования картинок, и Workbox позволяет эти практики применять буквально одной строчкой. В данном случае я задаю, что хочу кешировать не более чем 10 элементов.
Существует еще рецепт для production-ready, стабильно работающего офлайн-фолбека всевозможных сценариев.
Кеширование самих страниц.
Кеширование статических ресурсов, а именно JavaScript- и CSS-файлов.
Последнее добавление в версии 6.1 — разогрев рантайм-кеша, когда мы не просто задаем декларативно адрес и стратегию, а еще сразу в фоновом режиме эти ресурсы пытаемся предзагрузить.
Ссылка со слайда
Что делать, если нашему приложению нужна своя собственная стратегия? Workbox 6 имеет инструменты и для этого случая, когда нужно задать свою логику запросов, при этом сохранить подход, при котором мы можем использовать ее в роутинге, и все другие плюшки, например стандартные плагины Workbox.
В моем примере мы сделаем стратегию, которая будет обращаться одновременно и к кешу, и в сеть, после чего выдавать приложению то, что пришло быстрее.
Итак, что нам нужно сделать? Нам нужно расширить базовый класс в стратегии, назовем его CacheNetworkRace.
Ссылка со слайда
В этом классе нужно реализовать метод с названием _handle, куда мы передаем сам HTTP-запрос и — очень важно — экземпляр класса StrategyHandler…
Ссылка со слайда
Ссылка со слайда
… который будет содержать очень удобные методы для разработчика. Мы можем написать полностью с нуля всю эту пинг-понг-логику запросов в сеть и кеширования, а можем использовать удобный метод из этого класса fetchAndCachePut. То есть мы идем в сеть и сразу, если получили ресурс, кладем его в кеш для дальнейшего использования.
Ссылка со слайда
Аналогично можно не обращаться напрямую к API Cache Storage, а использовать удобный метод для поиска этого ресурса.
Что нам остается? Реализовать ту самую гонку в виде: «Какой промис первым выполнится успешно, тот мы и отдаем». Тут же можно сделать обработку ошибок.
Чтобы не запутаться в множестве вариантов использования Workbox, я сделал такую схему, где расположил на шкале гибкости против автоматизации все возможные варианты использования. Я думаю, мейнстрим — это все-таки использование модулей и их методов. Если уходить в сторону гибкости, можно начинать со своих плагинов и, если нужно, написать свою стратегию. Если в сторону автоматизации — идут рецепты и вариант, который мы сегодня даже не рассматривали: генерация сервис-воркера полностью с нуля через утилиту командной строки.
Друзья, мне осталось показать только некоторые интересные и полезные ресурсы. Вернемся к репозиторию, где вы найдете исходный код нашего демо-приложения, как оно работает, можете сразу увидеть ссылку на онлайн-версию. Все это настроено и работает на Azure Static Web Apps. Я вам рекомендую попробовать этот способ хостинга статических веб-приложений, который максимально автоматизирует весь цикл приложения — вы указываете только GitHub-репозиторий, его ветку, и через несколько мгновений ваше приложение, собранное и задеплоенное, находится уже в сети.
Продолжить общение на тему прогрессивных веб-приложений и сервис-воркеров я вам предлагаю в русскоязычном сообществе pwa_ru в телеграме. Еще одна интересная ссылка ведет на другой GitHub-репозиторий, где мы собрали максимально широкий набор ресурсов о прогрессивных веб-приложениях, сервис-воркерах, кешировании на русском языке. Там же вы найдете целую кучу примеров PWA в production и из глобального интернета, и из рунета. Я вам обещаю, многие посещаемые вами сайты, которые вы используете достаточно часто, — это прогрессивные веб-приложения или, по крайней мере, они используют части сервис-воркеров для оптимизации вашего пользовательского опыта.
Друзья, прогрессивные веб-приложения — это про улучшение пользовательского опыта. Workbox — это про улучшение опыта разработчика. Давайте создавать быстрые и удобные веб-приложения и получать от этого удовольствие. Спасибо вам огромное за внимание.
От докладчика:
Среди отзывов, полученных мной после этого доклада, занявшего второе место по полезности по результатам опроса после конференции, был такой: «Краткий пересказ документации Workbox». Что ж, в какой-то степени это действительно так: я рассказал пошаговую историю превращения «обычного» веб-приложения в прогрессивное с помощью этой замечательной библиотеки. Буду очень рад, если доклад и конспект вдохновят вас и помогут начать ваше собственное путешествие в мир сервис-воркеров и PWA.
— Здравствуйте, уважаемые веб-разработчики, привет, любители фронтенда. Если описать мой сегодняшний доклад самыми общими словами и уместить это описание в одно предложение, то он о том, как сделать наши фронтенд-приложения быстрее и удобнее для наших уважаемых пользователей и как самим разработчикам при этом получать удовольствие от процесса разработки.
Меня зовут Максим Сальников, я отвечаю за успех облачных разработчиков в компании Microsoft, и я большой любитель технических сообществ. Я организовываю митапы, конференции и воркшопы. Вы можете увидеть меня как докладчика на русскоязычных и англоязычных конференциях, посвященных вебу и прогрессивным веб-приложениям в частности.
Сегодня обсудим с вами, что происходит в мире PWA на данный момент, посвятим основную массу слайдов и времени доклада сервис-воркеру, а именно его автоматизации. Также я поделюсь ссылками на ресурсы, где можно продолжить общение на русском языке по этой тематике.
Что сегодня происходит с прогрессивными веб-приложениями? Американские горки — какие-то новости радуют, какие-то не очень.
Например, компания Mozilla анонсировала, что в следующей версии Firefox функциональность PWA поддерживаться не будет. Немного кликбейтный заголовок, обозначающий то, что компания остановила разработку той части PWA, которая отвечает за установку веб-приложения на устройство. Но это толком там и не работало, было всегда скрыто за флагом, так что это не такая уж большая новость. К счастью, всё, что касается API сервис-воркера, остается, и разработка продолжается.
Компания Google радует — теперь прогрессивные веб-приложения можно монетизировать, используя API для продажи цифровых товаров на их площадке Google Play. Для этого, правда, придется PWA обернуть в нативную оболочку мобильного приложения. К счастью, сделать это можно легко, используя инструмент от той же компании Google — Trusted Web Activity, TWA.
Компания Apple на своей конференции для разработчиков анонсировала, что 16 API, связанных с доступом к аппаратным возможностям устройств, в ближайшее время не будут реализованы в WebKit (и соответственно, в Safari), потому что по наличию или отсутствию этих API и их возможностей можно составить цифровой профиль пользователя и тем самым нарушить его приватность.
Хорошие новости от компании Microsoft. Инструмент PWA Builder, позволяющий создавать дистрибутивы, которые мы можем загружать в магазины приложений, живет и развивается. И всё проще и проще становится отправлять наши прогрессивные веб-приложения в натуральном виде в магазин приложений Microsoft Store.
Когда смотришь на подобные заголовки, складывается ощущение, что веб форкнули — какие-то компании ушли в сторону приватности, при этом страдает функциональность. Какие-то, наоборот, ушли в сторону функциональности — при этом, возможно, страдает приватность.
Ссылка со слайда
Что делать нам, разработчикам, как разрабатывать современные веб-приложения? Ответ — давайте следовать веб-стандартам. Все API, которые мы с вами будем сегодня рассматривать — часть веб-стандартов или, как минимум, черновики. То есть они прошли все необходимые обсуждения, слушания, все формальные процедуры, чтобы стать тем, что потенциально может стать веб-стандартом, если он сейчас в статусе черновика.
Технически прогрессивные улучшения или, как механизм для этого, feature detection — то, что нам известно в мире фронтенда с незапамятных времен.
Ссылки со слайда: первая, вторая
Как понять все эти термины? PWA — что это, как это связано с сервис-воркером, что включает в себя сервис-воркер? Я сделал простую диаграмму, чтобы задать контекст нашей сегодняшней дискуссии. Под идеей PWA понимаются два концепта, связанных с веб-приложениями: возможность их установки на устройства пользователей и интересные возможности через набор новых web-API.
Все эти возможности используются через сервис-воркер, который служит основной частью того, что мы называем идеей PWA, но PWA — это не только сервис-воркер. Если мы копнем поглубже, то обнаружим, что сервис-воркер API — это целое семейство API, множество методов, и большинство из них так или иначе связано с работой с сетевыми запросами. И именно на этом уровне работает наш, сегодня пока еще не названный, герой.
Из многообразия этого подуровня API что-то связано с кешированием, но не все.
Ссылка со слайда
Если вам нужна мотивация в плане количественных показателей популярности сервис-воркеров — 1% из выборки сайтов, которые находятся в HTTP Archive, используют сервис-воркеры. Рост заметен, не взрывной на текущий момент времени, но и останавливаться он не планирует.
Ссылка со слайда
Может быть, следующая цифра вас воодушевит больше. 1% тех самых страниц под управлением сервис-воркеров обеспечивает почти пятую часть веб-трафика, что говорит о том, что в этот 1% страниц входят популярные и часто посещаемые ресурсы, то есть достаточно известные.
Почему наблюдается такая популярность сервис-воркеров именно со стороны известных веб-ресурсов?
Удобство для пользователей, все сводится к этому. Возвратимся к главному слогану нашего доклада — удобные и быстрые приложения.
- Действительно, почему бы не сделать так, что веб-приложения будут доступны всегда, вне зависимости от статуса подключения, если соответствующие API имеются?
- Почему бы не настроить действительно умное кеширование и переиспользовать данные, которые мы когда-либо загрузили?
- Почему бы не сделать так, что действия пользователей, которые они совершили офлайн, никуда не пропадают, а тщательно записываются и, если нужно, отправляются на сервера автоматически при первой возможности подключения. Например, для аналитики это очень важно?
- Если соединение нестабильно, почему бы не сделать так, чтобы это не нарушало пользовательский опыт? Все возможности имеются.
- Следующая идея — обновление приложения и данных, которые использует приложение. К этому мы привыкли при использовании нативных мобильных приложений. То есть они где-то в фоне себя потихоньку обновляют, так что мы всегда работаем с самой последней версией.
- Кроме того, современные устройства оснащены массой интересных API — и аппаратных, и программных, так что не использовать их странно, если это релевантно для конкретного приложения и конкретного бизнес-сценария.
При этом мы оставляем всю природу и силу веба, если мы используем именно веб-технологии — общедоступность, простоту обмена ссылками и открытость платформы.
Если все это так удобно для пользователей, почему каждое приложение не использует сервис-воркер?
Ссылка со слайда
Не все так просто с точки зрения разработчиков. Шутка из 2019 года все еще имеет под собой основания. Я вольно ее перевел и возьму смелость нарушить идею о том, что хорошая шутка в объяснении не нуждается — все же объясню, что тут имеется в виду.
Ссылка со слайда
Дело в том, что в теории работа с сервис-воркером выглядит достаточно просто. Что такое сервис-воркер? Во-первых, это JavaScript-код. Во-вторых, это код, который исполняется в отдельном контексте относительно основного кода нашего приложения. В-третьих, это код, который исполняется только как ответ на какие-то события (events).
Вот три базовых события, которые позволяют нам сделать, допустим, офлайн-версию самого приложения или программной оболочки или application shell.
Событие install — кладем нужные ресурсы в кеш: index.html, главный бандл JavaScript, главный бандл CSS, может быть, что-то еще.
Ссылка со слайда
Событие activate — управляем версиями, если приложение обновилось.
Ссылка со слайда
Событие fetch — тут мы немного обманываем основное приложение тем, что в ответ на все явные и неявные HTTP, a точнее HTTPS-запросы мы можем выдавать данные не из интернета, а те, что мы до этого закешировали. Это в теории.
Ссылка со слайда
В руководстве вы найдете примерно одинаковые куски кода, примерно в сотню строчек. (Я показываю этот самый кусочек кода исключительно для демонстрации объема.) Найдете наивную реализацию того, что можно назвать офлайн-приложением. Наивную и не готовую для жизни в production, потому что не хватает достаточно важных вещей — автоматизации, настроек, расширяемости.
Действительно, если мы говорим не о приложении «Hello, World!», а о том, которое растет, меняет список ресурсов — ведь даже те ресурсы, что у нас есть, могут добавлять в свои названия хеш-суммы, чтобы как-то работать с http-кешированием. Все это нужно предусмотреть.
Забота о пользователе: если мы что-то кешируем, то должны убедиться, что это умное кеширование, что мы не скачиваем байты данных, которые нам не нужно скачивать, если этот ресурс не обновился. В этом наборе строчек мы точно не поместим весь набор нужных фолбэков, а они нам понадобится в вебе как в среде исполнения нашего приложения.
Это зоопарк всех возможных сценариев, платформ, браузеров, типов подключений. Кроме того, мы не получим удовольствие как разработчики — все-таки мы хотим иметь полный контроль над тем, что мы разрабатываем, нужен серьезный подход к тестированию и отладке.
Ссылка со слайда
Даже если мы сделаем все эти вещи, а это уже будет не сотня строк, а на порядок больше, то приложение все еще не готово для production, потому что мы наверняка что-то из этого нового расширенного списка забыли. В итоге мы придем к той самой шутке про необходимость нового домена, потому что версия почему-то зависла.
Ссылка со слайда
Именно поэтому, если мы посмотрим на статистику HTTP Archive, примерно треть всех текущих сервис-воркеров в выборке адресов сделаны с помощью Workbox или его предков. Вот мой личный топ особенностей этой библиотеки, из-за которых мне она так нравится:
- Уровень абстракций настолько комфортен для разработчика, насколько это возможно. У нас все еще есть полный контроль, полное понимание того, что именно мы делаем — то есть не ждите большой кнопки «сделать круто». При этом мы избавлены от копания в глубоких технических деталях HTTP-запросов, алгоритмов кеширования, если нам это не нужно. Если нужно, то можем опуститься и на этот уровень.
- Где уместно, возвращается декларативность, применимая к идее кеширования, что тоже очень значительно упрощает и делает комфортной саму разработку.
- Модульность помогает нам и системам сборки оптимизировать размер итогового файла сервис-воркера, неиспользуемый код не окажется в production.
- Если нужно, мы всегда можем расширить текущие модули и текущие методы.
- Функциональность «из коробки» настолько широка, что покроет, я думаю, процентов 90 всех возможных сценариев, которые потребуются при создании, в частности, офлайн-приложения.
- Мощный инструментарий: инструменты командной строки, модули для Node, плагины для систем сборки.
- Очень важный момент — бесплатность, открытый исходный код, активная разработка и поддержка со стороны Google и сообщества разработчиков.
Я надеюсь, что убедил вас попробовать. Давайте сделаем это незамедлительно.
Помните тот самый демонстративный кусок кода, несколько десятков строчек? В Workbox это будет одна строчка — вызов одного конкретного метода, который называется precacheAndRoute. Его название говорит само за себя: Workbox, закешируй этот набор ресурсов и настрой роутинг, чтобы эти ресурсы выдавались из кеша, если это возможно. Как параметр этому методу мы передаем массив, содержащий конкретный список ресурсов.
Чтобы заменить эту переменную, которая исполняет роль плейсхолдера в исходном сервис-воркере, и полностью автоматизировать процесс подготовки сервис-воркера, нам нужно сделать несколько шагов.
В первую очередь — заполнить эту переменную конкретным списком файлов (и их хеш-сумм), которые нам необходимо закешировать.
Нативные импорты JavaScript в сервис-воркерах пока еще не работают, поэтому сервис-воркер будет необходимо собрать.
В конце концов нужно сообщить приложению, что теперь оно работает под управлением сервис-воркера.
При этом первые пару пунктов неплохо бы делать при каждом билде приложения. Давайте приступим к этим шагам незамедлительно. Для этого нам потребуется установить модуль workbox-build, который нам поможет с пунктом номер один.
Это модуль для Node, соответственно добавим немного JavaScript-кода.
В конфигурации мы укажем тот самый исходный сервис-воркер и адрес итогового сервис-воркера.
Самое главное — мы должны объяснить Workbox, какие именно файлы составляют ту самую программную оболочку, тот самый application shell. К счастью, это делается очень удобным методом glob-шаблонов. Я гарантирую, что вы сможете настроить необходимую выборку ресурсов для вашего даже сложного по конфигурации веб-приложения. В этом конфиге есть много других свойств, которые позволяют вам совершенно точно затюнинговать этот процесс.
Вызов метода injectManifest с говорящим названием.
Это позволит нам внедрить массив, который Workbox для нас собрал на основе шаблонов, вместо переменной, которая исполняет роль плейсхолдера. В итоге у нас получится примерно такого вида сервис-воркер с одним-единственным методом precacheAndRoute.
Следующий шаг — бандлинг. Заодно сделаем минификацию, чтобы следовать всем идеям современной веб-разработки. Можете использовать свой любимый инструмент сборки, в моем случае это Rollup.
В общем случае нам понадобятся три плагина.
Ссылка со слайда
Как их настроить, можно посмотреть на этом слайде. Базовая настройка требуется только в плагине rollup-replace, который позволяет выбирать режим Workbox, development или production, заменой строки в исходном коде Workbox.
Чем отличаются режимы? В режиме production вся отладочная информация будет полностью исключена, в режиме development вы увидите детальный лог в консоли браузера, который позволяет точно прослеживать, что именно делает Workbox. Очень удобно.
Terser сделает минификацию, чтобы получить примерно такой вид итогового сервис-воркера.
Даже не пытайтесь понять, что здесь происходит, этот код не для человека, а для машин — а именно для браузеров. Хочу только заметить, что при каждом очередном билде нашего приложения итоговый файл сервис-воркера будет отличаться от предыдущего хотя бы потому, что мы туда внедряем хеш-суммы тех ресурсов, которые просим закешировать. Это важно для понимания того, как работает механизм обновления версий в Workbox.
Осталось интегрировать сборку сервис-воркера в общий билд приложения.
Ссылка со слайда
Последний шаг из нашего набора — регистрация в приложении. Тут можно пойти путем вызова нативных методов, метод register для объекта сервис-воркер, а можно опять обратиться за помощью к нашему герою — Workbox.
С использованием модуля workbox-window у нас есть удобный метод для регистрации — на самом деле это синтаксический сахар для нативного метода, плюс там сразу внедрена лучшая практика по моменту регистрации сервис-воркера, а именно в событии window.onload. Чтобы не конкурировать за сетевые и процессорные ресурсы с основным потоком JavaScript, мы откладываем регистрацию сервис-воркера настолько, насколько это возможно.
Кроме того, становится доступен удобный механизм для показа вопроса про обновление версии — я называю это «вежливым обновлением».
Вероятно, при серфинге в вебе вы видели диалог, возникающий на некоторых сайтах, который спрашивает: не хотите ли вы обновить страничку для работы с ее новой версией? Что это значит? Во-первых, этот сайт находится под управлением сервис-воркера. Во-вторых, то, что вы сейчас видите на экране, было извлечено из кеша в вашем устройстве и, скорее всего, это доступно и полностью офлайн. В-третьих, на сервере находится обновленная версия, поэтому сервис-воркер дает сигнал приложению спросить, не хотите ли вы эту новую версию получить — и вы сами решаете, да или нет.
Допустим, если вы начали заполнять большую форму, и через секунду прилетело это сообщение, то, может быть, вы откажетесь, потому что все данные могут быть потеряны. Тут мы возвращаемся к хорошему опыту пользователя — к вежливому процессу обновления.
Исходный код именно для этой части сервис-воркера есть в репозитории по адресу aka.ms/workbox6. Там находится код сегодняшнего демонстрационного приложения и ссылка на его онлайн-версию, чтобы вы могли с ним поиграть и посмотреть, какие процессы там происходят. Открывайте DevTools, вкладку Application, что я и сделаю прямо сейчас.
Итак, приложение — простой блог, сделаем его офлайн-готовым, то есть работающим вне зависимости от подключения к сети. Давайте посмотрим, как это выглядит.
Обратите внимание на правую нижнюю часть — Workbox нам выдал все подробные детали того, что он закешировал при первой загрузке приложения. Уходим в режим офлайн, обновляем страничку — программная оболочка работает, потому что файлы извлекаются уже не из сети с массой сетевых ошибок, потому что мы в режиме офлайн, а из кеша.
При этом мы, конечно, потеряли потребляемые данные — те статьи, которые были на главной странице, потому что они уже загружались в рантайм. Это мы тоже исправим.
Что мы в итоге получили? Полностью работающую офлайн-оболочка приложения, управление версиями со стороны Workbox и детализированную информацию для разработчиков.
Как я обещал, давайте исправим рантайм-кеширование, чтобы и статьи тоже при их первой загрузке аккуратно складывались в кеш для дальнейшей работы в офлайне.
Посмотрим на исходный сервис-воркер. Все начинается с импортов, конкретных методов, которые нам нужны. Помните пользовательский опыт? Никакого лишнего, мертвого кода.
Если мы в блоге используем аватары из сервиса Gravatar, для этого мы можем настроить самую консервативную стратегию — всегда брать их из кеша, если они там доступны с предыдущей загрузки. Как вы видите, этот метод очень декларативен, то есть это выглядит как настройка роутинга. Для адресов, который попадают под этот шаблон, в данном случае я его задаю через RegExp, мы просим Workbox использовать стратегию Cache First.
Если речь идет про другие типы информации, которые приложение загружает в процессе использования, например, про список статей, то тут больше подходит стратегия Network First. Список статей может обновляться достаточно часто, особенно если мы делаем новостной ресурс. Там всегда есть смысл попробовать сеть: если сервер доступен, то мы всегда будем загружать свежую информацию, если нет, возьмем из кеша, а еще можно об этом уведомить пользователя.
Самая интересная стратегия предлагается для конкретной статьи или конкретного поста. Называется Stale While Revalidate, и говорит она следующее: Workbox, попробуй взять данные для этого адреса из кеша, если они там есть, и отправь их в приложение, чтобы оно их мгновенно показало. В это же самое время сходи и посмотри, есть ли по этому адресу в сети обновление. Если есть — загрузи и положи его в кеш для следующего использования.
В то же время в моем примере кода вы можете увидеть, что используется плагин Broadcast Update, который дает нам возможность отправить сообщение приложению. Если данные обновились, можно спросить пользователя: «Не желаете ли получить обновленную статью?»
Есть множество готовых для использования стратегий и хороший набор плагинов, который позволяет нам эти стратегии тюнинговать, — уже встроенные в Workbox.
Ссылка со слайда
Перейдя на следующий уровень абстракции, мы в версии шесть Workbox обнаружим такой концепт, как рецепты, которые позволяют еще проще настраивать, например, рантайм-кеширование.
Если мы всегда знаем, что сам шрифт с Google-серверов и CSS к нему доступны по таким-то адресам, и к ним всегда подходит одна и та же стратегия — можно реализовать это буквально одной строчкой. Если нужно, мы можем это каким-то образом настроить. В моем примере я задал свое имя кешу, который будет в браузере.
Ссылка со слайда
Аналогично с картинками. Есть хорошие практики для динамического кеширования картинок, и Workbox позволяет эти практики применять буквально одной строчкой. В данном случае я задаю, что хочу кешировать не более чем 10 элементов.
Существует еще рецепт для production-ready, стабильно работающего офлайн-фолбека всевозможных сценариев.
Кеширование самих страниц.
Кеширование статических ресурсов, а именно JavaScript- и CSS-файлов.
Последнее добавление в версии 6.1 — разогрев рантайм-кеша, когда мы не просто задаем декларативно адрес и стратегию, а еще сразу в фоновом режиме эти ресурсы пытаемся предзагрузить.
Ссылка со слайда
Что делать, если нашему приложению нужна своя собственная стратегия? Workbox 6 имеет инструменты и для этого случая, когда нужно задать свою логику запросов, при этом сохранить подход, при котором мы можем использовать ее в роутинге, и все другие плюшки, например стандартные плагины Workbox.
В моем примере мы сделаем стратегию, которая будет обращаться одновременно и к кешу, и в сеть, после чего выдавать приложению то, что пришло быстрее.
Итак, что нам нужно сделать? Нам нужно расширить базовый класс в стратегии, назовем его CacheNetworkRace.
Ссылка со слайда
В этом классе нужно реализовать метод с названием _handle, куда мы передаем сам HTTP-запрос и — очень важно — экземпляр класса StrategyHandler…
Ссылка со слайда
Ссылка со слайда
… который будет содержать очень удобные методы для разработчика. Мы можем написать полностью с нуля всю эту пинг-понг-логику запросов в сеть и кеширования, а можем использовать удобный метод из этого класса fetchAndCachePut. То есть мы идем в сеть и сразу, если получили ресурс, кладем его в кеш для дальнейшего использования.
Ссылка со слайда
Аналогично можно не обращаться напрямую к API Cache Storage, а использовать удобный метод для поиска этого ресурса.
Что нам остается? Реализовать ту самую гонку в виде: «Какой промис первым выполнится успешно, тот мы и отдаем». Тут же можно сделать обработку ошибок.
Чтобы не запутаться в множестве вариантов использования Workbox, я сделал такую схему, где расположил на шкале гибкости против автоматизации все возможные варианты использования. Я думаю, мейнстрим — это все-таки использование модулей и их методов. Если уходить в сторону гибкости, можно начинать со своих плагинов и, если нужно, написать свою стратегию. Если в сторону автоматизации — идут рецепты и вариант, который мы сегодня даже не рассматривали: генерация сервис-воркера полностью с нуля через утилиту командной строки.
Друзья, мне осталось показать только некоторые интересные и полезные ресурсы. Вернемся к репозиторию, где вы найдете исходный код нашего демо-приложения, как оно работает, можете сразу увидеть ссылку на онлайн-версию. Все это настроено и работает на Azure Static Web Apps. Я вам рекомендую попробовать этот способ хостинга статических веб-приложений, который максимально автоматизирует весь цикл приложения — вы указываете только GitHub-репозиторий, его ветку, и через несколько мгновений ваше приложение, собранное и задеплоенное, находится уже в сети.
Продолжить общение на тему прогрессивных веб-приложений и сервис-воркеров я вам предлагаю в русскоязычном сообществе pwa_ru в телеграме. Еще одна интересная ссылка ведет на другой GitHub-репозиторий, где мы собрали максимально широкий набор ресурсов о прогрессивных веб-приложениях, сервис-воркерах, кешировании на русском языке. Там же вы найдете целую кучу примеров PWA в production и из глобального интернета, и из рунета. Я вам обещаю, многие посещаемые вами сайты, которые вы используете достаточно часто, — это прогрессивные веб-приложения или, по крайней мере, они используют части сервис-воркеров для оптимизации вашего пользовательского опыта.
Друзья, прогрессивные веб-приложения — это про улучшение пользовательского опыта. Workbox — это про улучшение опыта разработчика. Давайте создавать быстрые и удобные веб-приложения и получать от этого удовольствие. Спасибо вам огромное за внимание.
pepelsbey
Опять расшифровщики докладов вывалили полный дамп и навтыкали код картинками. Когда же вы перестанете лениво переупаковывать контент и начнёте писать полезные и удобные статьи по мотивам докладов? Это разные жанры, ребята.
BarakAdama
Вадим, позволю себе поспорить. Вы правы, что самостоятельный пост и доклад — это разные жанры. Поэтому для докладов мы используем специальную маркировку, чтобы не путать их. Если в названии есть слово «доклад» (давным-давно это было слово «лекция»), то это прежде всего видео с докладом, а бонусом расшифровка для тех, кто по каким-то причинам не любит или не может посмотреть видео. Запрос на текстовую расшифровку к докладам достаточно популярен на Хабре.
Часто доклады дают жизнь самостоятельным историям, но только там, где это актуально и возможно. Например, вот этот пост-победитель Технотекста 2020 про Node.js во фронтенде по мотивам доклада. В этом случае в названии уже не будет слова «доклад». Так эти жанры легко различать. Так это работает уже как минимум с 2015 года.
pepelsbey
Пост-победитель написал сам автор и там нет глупостей «друзья, спасибо за внимание», это полноценный текст статьи. Картинки там только для схем, а всё остальное нормально перенесено в текст.
У меня нет проблем с расшифровками. Только с ленивыми, как эта. Я с трудом читаю текст на слайдах, он мелкий и неконтрастный. Не говоря про код. Так почему не перенести это в текст? Потому, что это переупаковка, главная цель которой — быть не слишком сложной.
BarakAdama
Вадим, сейчас будет много текста :)
Честно говоря, я не понял вот эту ветвь дискуссии. А кто же ещё мог его написать по мотивам своего доклада? Конечно, автор. Это был пример в ответ на вопрос «когда». То есть статьи по мотивам уже выходят и будут выходить. Но вы лучше меня знаете, что далеко не все доклады дают жизнь статьям по мотивам, по разным причинам. А значит, всегда будут доклады, представленные исключительно в формате видео. И для таких докладов наличие простой расшифровки речи докладчика с минимальными правками и хронологически верно расставленными слайдами — это плюс. Да, это костыль, он не идеален, но с ним лучше, чем без него. Например, расшифровки позволяют найти такие видеодоклады в поиске по произвольным ключевым словам из текста доклада.
Мне понятно желание «расшифровать в текст» ещё и код на слайдах. Например, так его можно будет скопировать, проще будет указать на ошибку в нём и т. д. В расшифровках это неудобно делать, впрочем, это неудобно делать и при просмотре видео. Но слайды обычно содержат не просто код, но и доп.информацию (подписи, картинки, выделение цветом, какие-то комментарии). То есть речь уже идёт не о «скопировал-распознал-вставил», а об адаптации доклада в некоторое промежуточное состояние между расшифровкой и самостоятельной статьей, в которую нужно инвестировать время автора, чтобы корректно всё раскрыть. В условиях, когда расшифровка — это изначально «костыль» для видео и не конкурент статье, мне пока неочевидно, зачем инвестировать время именно в эту работу, а не в другую, например, в полноценную статью или даже новый доклад. Кроме того, это, кажется, первый запрос на подобную работу за многие годы (это 300+ опубликованных докладов). Поэтому пока не буду ничего обещать. Но подумаем.