Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
Как мы запустили
offline-версию cайта rg.ru
официально
1 000 000
Offline-версия уже доступна
для любого сайта
Доставка пиццы
Вкусная
пицца
Всё что угодно
Service Worker -
сердце оффлайн приложения
Позволяет
Позволяет
- КОНТРОЛИРОВАТЬ СТРАНИЦЫ
Позволяет
- КОНТРОЛИРОВАТЬ СТРАНИЦЫ
- ПЕРЕХВАТЫВАТЬ ЗАПРОСЫ
Позволяет
- КОНТРОЛИРОВАТЬ СТРАНИЦЫ
- ПЕРЕХВАТЫВАТЬ ЗАПРОСЫ
- КЕШИРОВАТЬ РЕСУРСЫ
Позволяет
- КОНТРОЛИРОВАТЬ СТРАНИЦЫ
- ПЕРЕХВАТЫВАТЬ ЗАПРОСЫ
- КЕШИРОВАТЬ РЕСУРСЫ
Принцип работы Service Worker
register
Принцип работы Service Worker
register install
Принцип работы Service Worker
register install activation
register
register
navigator
.serviceWorker
.register(
‘/sw.js’,
{ scope: ‘/article/’}
)
register
navigator
.serviceWorker
.register(
‘/sw.js’,
{ scope: ‘/article/’}
)
install
install
self.addEventListener(
‘install’,
event => {
....
setCache()
}
)
activation
activation
self.addEventListener(
‘activate’,
event => {
....
checkCache()
}
)
Принцип работы Service Worker
Слушаем события:
message
Принцип работы Service Worker
Слушаем события:
- MESSAGE
Принцип работы Service Worker
Слушаем события:
- MESSAGE
fetch
- FETCH
Принцип работы Service Worker
Слушаем события:
- MESSAGE
- FETCH
push
- PUSH
Принцип работы Service Worker
Слушаем события:
- MESSAGE
- FETCH
- PUSH
sync - SYNC
Подходы к построению
оффлайн приложения
1 Статика
1 Статика
HTML
1 Статика
HTML CSS
1 Статика
HTML CSS JS
1 Статика
HTML CSS JS
IMG / SVG / FONTS
2 Offline first
3 SPA
3 SPA
3 SPA
3 SPA
3 SPA
Идея создания
offline версии rg.ru
Как у них?
This page is not availiable
Reload More
This page is not availiable
Reload More
This page is not availiable
Reload More
This page is not availiable
Reload More
This page is not availiable
Reload More
Описание интерфейса
offline
offline
offline
offline
offline
Фильтруем контент
Как работает offline-версия
сайта rg.ru
Page
Page
register
SW
Page
install
Cache
SW
Page
activate
Clear
SW
Page
fetch
Filter
SW
self.addEventListener(‘fetch’, event => {
event.respondWith(
fetch(request)
.catch(() => {
return caches.match(offlineApp)...
Page SW
Update
Принцип работы приложения
Controller
Controller
index.html
Controller
Model
index.html
Controller
Model
{{...}}
View
index.html
Controller
HTML
Model
{{...}}
View
index.html
Доступность сети
Доступность сети
- ONONLINE
Доступность сети
- ONONLINE
- ONOFFLINE
Доступность сети
- ONONLINE
- ONOFFLINE
- navigator.onLine
Доступность сети
Google
Analytics
SEND
Проблемы...
Обновление данных
Проблема...
Проблема... Есть идеи?
Проблема... Есть идеи? setInterval?
Проблема... Есть идеи? setInterval? ...
Page
Page
new Date()
Time 1
Page
new Date()
Time 1
Local Storage
Reload
Page
new Date()
Time 2
Page
new Date()
Time 2
Local Storage
Time 1
Page
new Date()
Time 2
Local Storage
Time 1
ВРЕМЯ
ПОСЛЕДНЕГО
ПОСЕЩЕНИЯ
Page
new Date()
Time 2
Local Storage
Time 1
>15
Page
Update
periodicSync
registration.periodicSync.register({
tag: ‘updateData’,
minPeriod: 15 * 60 * 1000
...
})
Задержки
при получении данных
https://rg.ru/
offline
fetch(PATH_TO_OFFLINE_DATA)
.then(renderApp)
Запрос на получение данных
OfflineApp
OfflineApp
FETCH
OfflineApp
sendMsgToSW(‘getCacheResource’, {
resourceName: ‘OFFLINE_DATA’
})
Запрос на получение данных
Два Service Worker
в одном scope
PUSH NOTIFICATION
RG.RU
{ scope: ‘/article/’} { scope: ‘/rubrics/’}
RG.RU
{ scope: ‘/article/’} { scope: ‘/rubrics/’}
RG.RU
{ scope: ‘./’} { scope: ‘./’}
RG.RU
{ scope: ‘./’} { scope: ‘./’}
importScripts(‘offline’);
importScripts(‘notification’);
ServiceWorker.js
importScripts(‘offline’);
importScripts(‘notification’);
ServiceWorker.js
navigator
.serviceWorker
.register(‘/sw.js’)
.then(() => {
// Оффлайн: инициализация сервиса
initOfflineService();
// Увед...
Проксирование трафика
через ServiceWorker
Request to Service Worker ~ 9.0 s
Было
self.addEventListener(‘fetch’, event => {
event.respondWith(
fetch(event.request)
.catch(() => {
return caches.match(...
Стало
self.addEventListener(‘fetch’, event => {
if (
) {
event.respondWith(
fetch(event.request)
.catch(() => {
return cac...
Стало
self.addEventListener(‘fetch’, event => {
if (request.method === ‘GET’
) {
event.respondWith(
fetch(event.request)
....
Стало
self.addEventListener(‘fetch’, event => {
if (request.method === ‘GET’ &&
request.headers.get(‘accept’).includes(‘te...
Стало
self.addEventListener(‘fetch’, event => {
if (request.method === ‘GET’ &&
request.headers.get(‘accept’).includes(‘te...
Аналитика
Page
Page
get
Google
Analytics
DATA
Index DB
Index DB
- асинхронно
Index DB
- асинхронно
- транзакции
Index DB
- асинхронно
- транзакции
- индексы
Index DB
- асинхронно
- транзакции
- индексы
- большие объемы
Index DB
- асинхронно
- транзакции
- индексы
- большие объемы
- работа из SW
Index DB
- асинхронно
- транзакции
- индексы
- большие объемы
- работа из SW
Page
Page
pageview
DB
Page
pageview
DB
get
DATA
GA
+10% аудитории
Page DB
get
DATA
GA
Что мы имеем
на данный момент
Данные о посещаемости
Данные о посещаемости
3000 из Offline
30% - Desktop
Блокировка сайтов
302 редирект
Блокировка сайтов
Блокировка сайтов
self.addEventListener(‘fetch’, event => {
event.respondWith(
fetch(request)
.then(response => {
		
if (r...
Блокировка сайтов
self.addEventListener(‘fetch’, event => {
event.respondWith(
fetch(request)
.then(response => {
		
if (r...
Ошибки сервера 5xx
Ошибки сервера 5xx
self.addEventListener(‘fetch’, event => {
event.respondWith(
fetch(request)
.then(response => {
		
if (...
Ошибки сервера 5xx
self.addEventListener(‘fetch’, event => {
event.respondWith(
fetch(request)
.then(response => {
		
if (...
back end
back end front end
back end front end
PWA
Edge Firefox Chrome Opera
11 52
53
54
55
56
IE
11 15
57
58
59
60
61
49
56
49
10
10.1 44
45
46
Edge Firefox Chrome Opera iOS Safari
Android
Browser
Chrome for
Android
11 52
53
54
55
56
IE
11 15
57
58
59
60
61
49
56
49...
Резюме
- РАСШИРЕНИЕ ДОСТУПНОСТИ САЙТА
- ОБРАБОТКА ОШИБОК СЕРВЕРА
- РАБОТАЕТ УЖЕ СЕЙЧАС
Вопросы?
Максим Чагин
e-mail: MaxChagin@gmail.com
Алексей Чернышев
e-mail: mr.lozchka@gmail.com
skype: mr.lozchka
Ссылки по теме:
rg.ru/front2017/
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)
Upcoming SlideShare
Loading in …5
×

Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)

155 views

Published on

РИТ++ 2017, Frontend Сonf
Зал Мумбаи, 6 июня, 15:00

Тезисы:
http://frontendconf.ru/2017/abstracts/2575.html

Мы расскажем о построении работы действующей offline версии сайта на примере СМИ с миллионной аудиторией. О выборе стека технологий для решении поставленной задачи. О результатах эксплуатации с момента запуска.
В том числе: * Стратегия обновления данных в Service Worker * Проблемы и их решение при работе с оффлайн-средой * Сбор аналитики при отсутствии интернета

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Как мы запустили offline-версию сайта RG.RU / Алексей Чернышев, Максим Чагин (Российская Газета)

  1. 1. Как мы запустили offline-версию cайта rg.ru
  2. 2. официально 1 000 000
  3. 3. Offline-версия уже доступна для любого сайта
  4. 4. Доставка пиццы
  5. 5. Вкусная пицца
  6. 6. Всё что угодно
  7. 7. Service Worker - сердце оффлайн приложения
  8. 8. Позволяет
  9. 9. Позволяет - КОНТРОЛИРОВАТЬ СТРАНИЦЫ
  10. 10. Позволяет - КОНТРОЛИРОВАТЬ СТРАНИЦЫ - ПЕРЕХВАТЫВАТЬ ЗАПРОСЫ
  11. 11. Позволяет - КОНТРОЛИРОВАТЬ СТРАНИЦЫ - ПЕРЕХВАТЫВАТЬ ЗАПРОСЫ - КЕШИРОВАТЬ РЕСУРСЫ
  12. 12. Позволяет - КОНТРОЛИРОВАТЬ СТРАНИЦЫ - ПЕРЕХВАТЫВАТЬ ЗАПРОСЫ - КЕШИРОВАТЬ РЕСУРСЫ
  13. 13. Принцип работы Service Worker register
  14. 14. Принцип работы Service Worker register install
  15. 15. Принцип работы Service Worker register install activation
  16. 16. register
  17. 17. register navigator .serviceWorker .register( ‘/sw.js’, { scope: ‘/article/’} )
  18. 18. register navigator .serviceWorker .register( ‘/sw.js’, { scope: ‘/article/’} )
  19. 19. install
  20. 20. install self.addEventListener( ‘install’, event => { .... setCache() } )
  21. 21. activation
  22. 22. activation self.addEventListener( ‘activate’, event => { .... checkCache() } )
  23. 23. Принцип работы Service Worker Слушаем события:
  24. 24. message Принцип работы Service Worker Слушаем события: - MESSAGE
  25. 25. Принцип работы Service Worker Слушаем события: - MESSAGE fetch - FETCH
  26. 26. Принцип работы Service Worker Слушаем события: - MESSAGE - FETCH push - PUSH
  27. 27. Принцип работы Service Worker Слушаем события: - MESSAGE - FETCH - PUSH sync - SYNC
  28. 28. Подходы к построению оффлайн приложения
  29. 29. 1 Статика
  30. 30. 1 Статика HTML
  31. 31. 1 Статика HTML CSS
  32. 32. 1 Статика HTML CSS JS
  33. 33. 1 Статика HTML CSS JS IMG / SVG / FONTS
  34. 34. 2 Offline first
  35. 35. 3 SPA
  36. 36. 3 SPA
  37. 37. 3 SPA
  38. 38. 3 SPA
  39. 39. 3 SPA
  40. 40. Идея создания offline версии rg.ru
  41. 41. Как у них?
  42. 42. This page is not availiable Reload More
  43. 43. This page is not availiable Reload More
  44. 44. This page is not availiable Reload More
  45. 45. This page is not availiable Reload More
  46. 46. This page is not availiable Reload More
  47. 47. Описание интерфейса
  48. 48. offline
  49. 49. offline
  50. 50. offline
  51. 51. offline
  52. 52. offline
  53. 53. Фильтруем контент
  54. 54. Как работает offline-версия сайта rg.ru
  55. 55. Page
  56. 56. Page register SW
  57. 57. Page install Cache SW
  58. 58. Page activate Clear SW
  59. 59. Page fetch Filter SW
  60. 60. self.addEventListener(‘fetch’, event => { event.respondWith( fetch(request) .catch(() => { return caches.match(offlineApp); }); ); });
  61. 61. Page SW Update
  62. 62. Принцип работы приложения
  63. 63. Controller
  64. 64. Controller index.html
  65. 65. Controller Model index.html
  66. 66. Controller Model {{...}} View index.html
  67. 67. Controller HTML Model {{...}} View index.html
  68. 68. Доступность сети
  69. 69. Доступность сети - ONONLINE
  70. 70. Доступность сети - ONONLINE - ONOFFLINE
  71. 71. Доступность сети - ONONLINE - ONOFFLINE - navigator.onLine
  72. 72. Доступность сети Google Analytics SEND
  73. 73. Проблемы...
  74. 74. Обновление данных
  75. 75. Проблема...
  76. 76. Проблема... Есть идеи?
  77. 77. Проблема... Есть идеи? setInterval?
  78. 78. Проблема... Есть идеи? setInterval? ...
  79. 79. Page
  80. 80. Page new Date() Time 1
  81. 81. Page new Date() Time 1 Local Storage
  82. 82. Reload
  83. 83. Page new Date() Time 2
  84. 84. Page new Date() Time 2 Local Storage Time 1
  85. 85. Page new Date() Time 2 Local Storage Time 1 ВРЕМЯ ПОСЛЕДНЕГО ПОСЕЩЕНИЯ
  86. 86. Page new Date() Time 2 Local Storage Time 1 >15
  87. 87. Page Update
  88. 88. periodicSync
  89. 89. registration.periodicSync.register({ tag: ‘updateData’, minPeriod: 15 * 60 * 1000 ... })
  90. 90. Задержки при получении данных
  91. 91. https://rg.ru/ offline
  92. 92. fetch(PATH_TO_OFFLINE_DATA) .then(renderApp) Запрос на получение данных
  93. 93. OfflineApp
  94. 94. OfflineApp FETCH
  95. 95. OfflineApp
  96. 96. sendMsgToSW(‘getCacheResource’, { resourceName: ‘OFFLINE_DATA’ }) Запрос на получение данных
  97. 97. Два Service Worker в одном scope
  98. 98. PUSH NOTIFICATION
  99. 99. RG.RU { scope: ‘/article/’} { scope: ‘/rubrics/’}
  100. 100. RG.RU { scope: ‘/article/’} { scope: ‘/rubrics/’}
  101. 101. RG.RU { scope: ‘./’} { scope: ‘./’}
  102. 102. RG.RU { scope: ‘./’} { scope: ‘./’}
  103. 103. importScripts(‘offline’); importScripts(‘notification’); ServiceWorker.js
  104. 104. importScripts(‘offline’); importScripts(‘notification’); ServiceWorker.js
  105. 105. navigator .serviceWorker .register(‘/sw.js’) .then(() => { // Оффлайн: инициализация сервиса initOfflineService(); // Уведомления: инициализация сервиса initNotifyService(); })
  106. 106. Проксирование трафика через ServiceWorker
  107. 107. Request to Service Worker ~ 9.0 s
  108. 108. Было self.addEventListener(‘fetch’, event => { event.respondWith( fetch(event.request) .catch(() => { return caches.match(‘offlineApp’); })
  109. 109. Стало self.addEventListener(‘fetch’, event => { if ( ) { event.respondWith( fetch(event.request) .catch(() => { return caches.match(‘offlineApp’); })
  110. 110. Стало self.addEventListener(‘fetch’, event => { if (request.method === ‘GET’ ) { event.respondWith( fetch(event.request) .catch(() => { return caches.match(‘offlineApp’); })
  111. 111. Стало self.addEventListener(‘fetch’, event => { if (request.method === ‘GET’ && request.headers.get(‘accept’).includes(‘text/html’) && ) { event.respondWith( fetch(event.request) .catch(() => { return caches.match(‘offlineApp’); })
  112. 112. Стало self.addEventListener(‘fetch’, event => { if (request.method === ‘GET’ && request.headers.get(‘accept’).includes(‘text/html’) && !request.headers.has(‘range’)) { event.respondWith( fetch(event.request) .catch(() => { return caches.match(‘offlineApp’); })
  113. 113. Аналитика
  114. 114. Page
  115. 115. Page get Google Analytics DATA
  116. 116. Index DB
  117. 117. Index DB - асинхронно
  118. 118. Index DB - асинхронно - транзакции
  119. 119. Index DB - асинхронно - транзакции - индексы
  120. 120. Index DB - асинхронно - транзакции - индексы - большие объемы
  121. 121. Index DB - асинхронно - транзакции - индексы - большие объемы - работа из SW
  122. 122. Index DB - асинхронно - транзакции - индексы - большие объемы - работа из SW
  123. 123. Page
  124. 124. Page pageview DB
  125. 125. Page pageview DB get DATA GA
  126. 126. +10% аудитории Page DB get DATA GA
  127. 127. Что мы имеем на данный момент
  128. 128. Данные о посещаемости
  129. 129. Данные о посещаемости
  130. 130. 3000 из Offline
  131. 131. 30% - Desktop
  132. 132. Блокировка сайтов
  133. 133. 302 редирект Блокировка сайтов
  134. 134. Блокировка сайтов self.addEventListener(‘fetch’, event => { event.respondWith( fetch(request) .then(response => { if (response.status === 0) { return caches.match(WARNING); } if (response) return response; }) .catch(...)
  135. 135. Блокировка сайтов self.addEventListener(‘fetch’, event => { event.respondWith( fetch(request) .then(response => { if (response.status === 0) { return caches.match(WARNING); } if (response) return response; }) .catch(...)
  136. 136. Ошибки сервера 5xx
  137. 137. Ошибки сервера 5xx self.addEventListener(‘fetch’, event => { event.respondWith( fetch(request) .then(response => { if (response.status >= 500 || response.status <= 504) { return caches.match(WARNING); } if (response) return response; }) .catch(...)
  138. 138. Ошибки сервера 5xx self.addEventListener(‘fetch’, event => { event.respondWith( fetch(request) .then(response => { if (response.status >= 500 || response.status <= 504) { return caches.match(WARNING); } if (response) return response; }) .catch(...)
  139. 139. back end
  140. 140. back end front end
  141. 141. back end front end
  142. 142. PWA
  143. 143. Edge Firefox Chrome Opera 11 52 53 54 55 56 IE 11 15 57 58 59 60 61 49 56 49 10 10.1 44 45 46
  144. 144. Edge Firefox Chrome Opera iOS Safari Android Browser Chrome for Android 11 52 53 54 55 56 IE 11 15 57 58 59 60 61 49 56 49 10 10.1 44 45 46 10.2 10.3 9.3 4.4.4 56 4.4 57
  145. 145. Резюме - РАСШИРЕНИЕ ДОСТУПНОСТИ САЙТА - ОБРАБОТКА ОШИБОК СЕРВЕРА - РАБОТАЕТ УЖЕ СЕЙЧАС
  146. 146. Вопросы? Максим Чагин e-mail: MaxChagin@gmail.com Алексей Чернышев e-mail: mr.lozchka@gmail.com skype: mr.lozchka
  147. 147. Ссылки по теме: rg.ru/front2017/

×