Pull to refresh

Comments 40

Несколько раз пытался разобраться с этими самыми SW, но все не хватало времени. А теперь все вопросы отпали, пойду прикручивать в паре мест.
Использую гугловский github.com/GoogleChrome/sw-toolbox и .networkFirst политику кэширования.

Остальные на первый взгляд сладкие варианты кэширования как то .cacheFirst чреваты и требуют многодневного тестирования, и что важно, сложного обслуживания/поддержки.
Не могу не добавить свои рассуждения по SW:
  1. Поддержка браузеров!

  2. При использовании SW как прокси мы получаем довольно не плохую задержку в загрузке (-5% -5% +25%)
  3. Пуши — почему то многие о них умалчивают когда говорят о SW а тем не менее это довольно крутая штука.

Как по мне, так использовать SW нужно очень обдуманно. Потому что базовые операции по кешированию отлично могут выполнить заголовки файлов. Отдал заголовок с кешем на месяц, и файл будет браться из кеша браузера. Выкатил новую версию файла, дописал v=number в url. Где здесь SW?
С оффлайном да, хорошая идея, но опять же много чего в оффлайн не засунешь.
1. Про поддержку браузеров.
Как я знаю поддержка в таких браузерах как Safari или Edge находится в разработке.
Поэтому данная технология довольно-таки перспективна на мой взгляд.
Ровно как и часть крупных приложений уже начинают использовать их на проде (twitter, tinder, pinterest, smashingmagazine).

2 и 3
-5% -5% +25% — как сказал Артём Белов: “… сначала забирает, а потом добавляет с лихвой...”
По поводу прокси, пушей и как настроить общение между воркером и веб-страницей ещё будет статья. Тут идея была расписать базовые стратегии для кэширования и как их использовать, по сути “на пальцах“.

Касательно, выставить заголовки и т.п.
Базовые средства оптимизации никто не отменяет)
Кешировать надо все, что только возможно (с умом естественно), просто SW может помочь сделать приложение более отзывчивым и ускорить его отображение пользователю.

По поводу оффлайна:
А всё ли надо засовывать в оффлайн? На мой взгляд нужно лишь класть критичные файлы (css, js, html) и правильно обрабатывать ситуацию, когда нет доступа к сети, оставляя пользователя в приложении, а не заставляя его ждать минуту и в итоге показать Динозаврика.
Статья задумывалась начальной в серии статей о SW API. Хочется понять, насколько тема интересна и полезна. Жду ваших комментариев и пожеланий.

В общем, продолжайте!
Спасибо большое)))
Как говориться, подписывайтесь, ставьте лайки и комментируйте)))

Все еще непонятно, чем кэширование js/css с помощью SW лучше обычного кэширования на основе заголовков. Можете привести конкретный пример, где решение с SW подходит лучше?

Отдать закешированный ответ, а в фоне скачать новый для следующего запроса.

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

Есть конкретный пример, где это имеет смысл?
Я чуть-чуть подправил код и для меня в принципе не страшно, если юзер еще один заход будет пользоваться старой версией приложения вместо того, чтобы получить задержку на скачивание нового бандла. В конце концов, я могу показать кнопку «доступна новая версия, обновить страницу».
в принципе не страшно, если юзер еще один заход будет пользоваться старой версией

Но бывают же и изменения, которые надо юзеру сразу доставить (например, старая версия кода несовместима с новой разметкой, которую генерит CMS, или с новым API).
Как отличать эти "важные" изменения от "неважных", чтобы SW отдавал закэшированную версию в одном случае, но не в другом?


И еще такой момент. В реальном приложении нельзя полагаться исключительно на SW — так как есть неподдерживающие его браузеры. Значит, у вас уже предусмотрена система кэширования с возможностью инвалидации кэша при новых релизах. Например, добавляем параметр ?v=< version> к url ресурсов. Или, согласно рекомендации от webpack, дописываем хэш файла, посчитанный при сборке.
В результате при изменении кода URL меняется — и SW не найдет измененный файл в своем кэше.


Я вот все пытаюсь найти реальный случай, где кэширование с SW имеет смысл и работает. Что за сайт/приложение, какая там стратегия кэширования, что именно кэшируется и как инвалидируется, и какой именно сценарий использования мы пытаемся улучшить с помощью SW.

SW это программа, которую вы пишете, а не фиксированная модификация поведения. Вы можете запрогарммировать его как хотите. Поэтому
В результате при изменении кода URL меняется — и SW не найдет измененный файл в своем кэше.
только если вы так запрограммируете. Срезайте ?v=3 в обработчике запроса в коде SW, например.
Как отличать эти «важные» изменения от «неважных
Тут аналогичный ответ — вы пишете код, так что как хотите. Добавьте параметр &major-version=3 например.

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


Наиболее осмысленное применение кэша в SW из примеров, которые я видел в интернете: пре-кэшинг файлов в связке с HTTP/2 Server Push — для решения проблемы с кэшем, присущей Server Push (например, тут).

В случае кэширования в cacheStorage (не обязательно в service-worker, оно доступно и для window) при отправке запроса на серв не нужно получать заголовок — можно перехватить, проверить на какой ресурс запрос, и отдать соответствующий response из cacheStorage. И все это локально. На клиенте. Потому что раньше предусмотрительно положили туда нужные пары request-respones. Поэтому если клиент оффлайн, pwa'шка может отдавать соответствующий response без обращения к серверу. В этом и суть оффлайн pwa. Запросы не уходят в сеть. А чтобы получить заголовок кэширования обычными методами серва, нужна сеть.
А чтобы получить заголовок кэширования обычными методами серва, нужна сеть.

Неправда. Если файл уже закэширован браузером после первого запроса, то последующие запросы к нему выполняются без сети. Я имею в виду безусловное кэширование типа Cache-Control:max-age=<много-много секунд> (в отличие от условного кэширования с ETag/If-Modified-Since).


Для самого первого запроса сеть, конечно, нужна. Ну так и с SW первый запрос требует сети, когда кэш еще не заполнен.

Неправда. Если файл уже закэширован браузером после первого запроса, то последующие запросы к нему выполняются без сети.

Ключевое здесь файл. Статика. В случае кэширования в cacheStorage можно положить text/html response. При чем положить заранее, при первом обращении к серверу. При чем respone на любой request.url. То есть фактически при первом обращении задать список доступных оффлайн страниц.
В случае кэширования в cacheStorage можно положить text/html response

Да, про такой сценарий я не подумал. Обычно саму страницу никто "жестко" (с Cache-Control: max-age) кэшировать не станет. В этом случае SW позволит сделать фоллбэк на оффлайн-режим при отсутствии сети.
Хотя лично мне кажется, что оффлайн режим имеет очень ограниченную область применения. Имхо, не так много реальных приложений, в которых можно сделать что-то осмысленное без сети (типа написания черновика письма в gmail).


То есть фактически при первом обращении задать список доступных оффлайн страниц.

Ясно, pre-caching. Причем, "доступных оффлайн" — здесь даже необязательная часть. Сама страница может требовать сети для работы, но мы все еще можем заранее для нее что-то подгрузить.

Обычно саму страницу никто «жестко» (с Cache-Control: max-age) кэшировать не станет
Зависит от сценария, который реализуется. Как правило при первом обращении кэшируется вся статика необходимая для работы сайта/приложения и какой-то список страниц: rg.ru последние N новостей и показывает плашку «Ой! У вас нет интернета.», видел магазин который клал в кэш сразу все инфо страницы, сайт рекламного агентства — страницы оферов и их описаний.
Почему-то про сервис-воркеры пишут только в контексте кэша и работы оффлайн.

Использую для выполнения фоновых операций, +push уведомления юзерам о статусе этих операций и возможном прекращении их выполнения(если видно что закрыты все вкладки).
Как результат например общая для всех вкладок область видимости/«глобальная асинхронность», то есть если юзер открыл сервис в нескольких вкладках он не может запустить занового идентичный процесс, т.к. этот процесс идет в едином сервис-воркере.

Да, в курсе про такие операции)
Это очень классная вещь)
Я хотел начать с базовых вещей, а далее, в последующих статьях хочется погрузиться в те же пуши, фоновые операции и в другие интересные вещи)
Простите, я возможно отстал от жизни, но неужели SW стал по настоящему доступен на всех устройствах, помнится пол года назад с ним были явные проблемы на устройствах Apple.
Про поддержку браузеров можете посмотреть в этом комменте
habrahabr.ru/company/2gis/blog/345552/#comment_10586162

О каких именно проблемах вы говорите? Поддержки сейчас нет в Safari — это правда, но как минимум SW в разработке для Safari и Edge.
Нужна статья о синхронизации и фоновом обновления кэша. Например когда используется cacheFirst и кэшируется вообще все. Статику понятно, можно версионированием кэшей контролировать, а вот с контентом пока только костыли использовал. Например пользователь из листинга ушел в карточку товара, там добавил его в корзину, возвращается на листинг, а ему отдает версия страницы из кэша в которой корзина пустая. Делал для этого historyArr[] в котором хранил все request.url и при определенном запросе на сервер обновлял contentCache чтобы контент всегда был актуальный, но так как немношк не разраб, чувствую что костыль не оч верный и есть нативная синхронизация для подобных вещей.
как я понимаю из вашего контекста, данная задача мало связана с SW.
Если мы говорим о SPA, то подобную задачу можно решить через тот же redux и управлением данными через store, то есть вы сами контролируете, какой листинг вы открыли и если есть данные в store, то запрос можно не делать, а брать данные прямиком из хранилища.
А можно просто настроить заголовки на сервере так, чтобы кэшировать статику и html, но не кэшировать JSON, а все данные заполнять через JS, подтягивая их через этот самый JSON? Зачем тут redux вообще.

Да, я понимаю, что сайт сломается, если отключить JavaScript, плюс могут быть микро-задержки на клиентский рендеринг — но проблему с кэшированием это ведь решит?
Настройка заголовков и кеша не спасает медленной скорости интернета.
Клиент будет делать запрос на сервер и ждать, когда загрузиться html и всё остальное.
В SW иначе, первым делом достаются данные из кеша SW, а потом остальное Тем самым время Time to Interactive сводится к минимуму, т.к. не зависит от сети.
Как итог показываем, что приложение работает, но проблема ответа в скорости сети (так себя ведут мобильные приложения)
Нет, не SPA, обычное PWA которое прикручивается к обычному интернет-магазину с обычным php на бэкенде. Контент в SW делится на imgCache, staticCache и contentCache.

Во время сёрфинга по сайту в contentCache пишется text/html и соответственно при cacheFirst отдается из кэша. Так вот именно его нужно обновлять при определенных действиях: добавили в корзину, удалил, добавил в избранное, к сравнению, лайк\дизлайк, оставил комментарий. Потому что он хранит контент до этих действий. Надеюсь так понятнее :)

И вот такой костыль решает задачу, но чувствую что есть нативное решение.
function updateCacheByName (cacheName,updateRequestsArray) {
caches.delete(cacheName)
.then(function(){
console.log('удалили кэш '+cacheName+' чтобы обновить');
caches.open(cacheName).then(cache => {
return cache.addAll(updateRequestsArray).then(function(){
console.log('история обновлена в кэше '+cacheName);
}).catch( err => {console.log(err);});
});
}).catch( err => {console.log(err);});
}
Я ответил Вам в личку, чтобы не понижать контекст статьи и в целом ее обсуждения)

Мне нравятся статьи, в которых последовательно наращивается уровень материала.


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


В общем, я за продолжение.

UFO just landed and posted this here
UFO just landed and posted this here
Недавно, один популярный web-сервис внедрил подход «offline first» (или как он там правильно называется). Так вот, однажды при использовании я не сразу заметил, что интернета нет, и продолжал пользоваться сервисом. При этом, несколько раз ловил дикий «ux confusing», если можно так выразится. И только потом заметил маленькую системную надпись от браузера (рядом с протоколом в адресной строке) — типа «сайт offline», или как-то так. Я был несколько расстроен, потому что понял что терял время и контент был невалидный, а взаимодействие фейковое. Ещё подумал про себя — «началось, начали тестить продвинутое кеширование и сервис-воркеры». Так это я разобрался, а что говорить про людей далёких от web-разработки.

Поэтому:
Существует проблема, когда браузер по умолчанию выдаёт вам сообщение о том, что вы офлайн

как по мне, так это не проблема, а вполне понятное, чёткое и однозначное информирование о том что интернета пока нет, займись чем-то другим!
Моё мнение, что для сервисов, где есть плотное взаимодействие с пользователем, или контентных сервисов — подход «offline first» неудачный. Он годится лишь для чисто клиентских самодостаточных приложений (типа как тот гудящий горн на google developers, который приводят везде в пример)

p.s. хотя подозреваю, я тут напутал и намешал с pwa..))
Тут на самом деле понамешано малость.
Да, PWA это про SW, но SW — это не про PWA.

> как по мне, так это не проблема, а вполне понятное, чёткое и однозначное информирование о том что интернета пока нет, займись чем-то другим!

Как я вижу в плане дизайна приложения был допущена ошибка, что пользователь явно не показал, что вы в Offline. По мне это решается довольно просто:
window.addEventListener('offline', () => showOfflineBar());

Это уже проблема приложения, а не SW. Как я выше писал в своей статье, наша задача не просто не показывать «динозаврика», а показать своего «динозаврика» в стиле нашего приложения и была «наша» кнопка «обновить».
Уточните пожалуйста, разве XHR стали синхронными по умолчанию? Также интересно узнать, какая проблема обернуть синхронный вызов localStorage в колбеки, промисы, генераторы – на выбор? Но прежде чем оборачивать вызов localStorage в асинхронный вызов, я бы хотел понять, зачем? Если максимальный размер хранилища 5Мб, то сколько же по вашему мнению будет извлечение этого объёма из оперативы в синхронном режиме? Наберется ли там хотя бы микросекунда?

Одним словом, вы не спутали здесь синхронное исполнение кода и вызов, блокирующий процесс?

Я ничего против воркеров и сервис-воркеров не имею, просто почему синхронность стала проблемой?
Почему никто не пишет так:
if (!('serviceWorker' in navigator)){ return; } 
Сама технология хороша, но с чего Вы решили, что Ваш сайт достоин кеширования у меня на компьютере? Сейчас это 1-2 сайта, потом 100+, зачем мне 5000+ мб шлака, да ещё синхронизирующегося… Не говоря уже о том, что SW жрут батарейку. Меня уже порядком достали сайты, которые хотят присылать мне уведомления или определить местоположения, хотя я к ним зашёл первый раз по ошибке гугла…

Через прошедшие годы смотрим на эту задумку и видим, что как всегда интересную технологию стали абьюзить все кому не лень. Прикручивать в нее не только уведомления, кеши, но и распределенные вычисления на клиентах у пользователей без их ведома. Тысячи воркеров на клиентах грузят проц как не в себя и пользователи негодуют. А все почему? Потому, что гугл не озаботился дать механизмы управления этой штукой в руки самого пользователя, а оставил все на откуп эффективным совам из компаний, которые эти сервисы с воркерами и пилят. В итоге количество статей "как навсегда заблокировать регистрацию service workers в chrome" растет как на дрожжах. Ну и правильно, туда ей и дорога.

Подскажите мне гулпцу, пожалуйста. В сервис ворках реализуется такой же механизм как у функций обратного вызова (callback)? Или это совершенно разные вещи, которые нельзя сопоставлять?

Sign up to leave a comment.