{"id":474624,"date":"2025-09-11T15:00:40","date_gmt":"2025-09-11T15:00:40","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=474624"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=474624","title":{"rendered":"<span>Push-Notifications \u0432 PWA \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435: \u043f\u043e\u043b\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0431\u0435\u0437 \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<blockquote>\n<p><strong>Service Worker + Push API + VAPID \u043a\u043b\u044e\u0447\u0438 + Notifications API = \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0435 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/strong> \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<\/blockquote>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0432\u0435\u0431-push \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438, \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u2014 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 iOS, \u0433\u0434\u0435 Apple \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 2023 \u0433\u043e\u0434\u0443.<\/p>\n<h3>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/h3>\n<p>\u0421\u0438\u0441\u0442\u0435\u043c\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u2014 \u044d\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438\u0437 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u041e\u043d\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432\u043c\u0435\u0441\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e\u0442 \u0432\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0434\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0441\u0432\u043e\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u043d\u043e \u0431\u0435\u0437 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<h4>\u041e\u0431\u0449\u0438\u0439 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b<\/h4>\n<ol>\n<li>\n<p><strong>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c<\/strong> \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0440\u0430\u0443\u0437\u0435\u0440<\/strong> \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u0441 \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0435\u0440\u0432\u0435\u0440<\/strong> \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 push-\u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 \u044d\u0442\u0443 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443<\/p>\n<\/li>\n<li>\n<p><strong>Push-\u0441\u0435\u0440\u0432\u0438\u0441<\/strong> \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p><strong>Service Worker<\/strong> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0435\u0433\u043e<\/p>\n<\/li>\n<li>\n<p><strong>Notifications API<\/strong> \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u0438 \u043f\u043e\u0439\u043c\u0435\u043c, \u043a\u0442\u043e \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0438 \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442.<\/p>\n<h4>1. Service Worker \u2014 \u0424\u043e\u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/h4>\n<p><strong>\u0420\u043e\u043b\u044c:<\/strong> JavaScript-\u0441\u043a\u0440\u0438\u043f\u0442, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0432 \u0444\u043e\u043d\u0435 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 push-\u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/p>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 push-\u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043e\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043a\u0430\u0437 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 Notifications API<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a DOM<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0422\u0440\u0435\u0431\u0443\u0435\u0442 HTTPS \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b (\u043a\u0440\u043e\u043c\u0435 localhost)<\/p>\n<\/li>\n<\/ul>\n<p>Service Worker \u2014 \u044d\u0442\u043e \u0442\u0438\u043f web worker, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u0430\u043a \u043f\u0440\u043e\u043a\u0441\u0438-\u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438, \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c \u0438 \u0441\u0435\u0442\u044c\u044e. Service Worker \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 (scope), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f origin (\u0434\u043e\u043c\u0435\u043d + \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b + \u043f\u043e\u0440\u0442) \u0438 \u043f\u0443\u0442\u0435\u043c.<\/p>\n<p><strong>\u041f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438:<\/strong> Service Worker \u2014 \u044d\u0442\u043e JavaScript \u0441\u043a\u0440\u0438\u043f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0444\u043e\u043d\u0435 \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043a\u0440\u044b\u043b \u0431\u0440\u0430\u0443\u0437\u0435\u0440. \u041e\u043d \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h3>\n<p>Service Worker \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e JavaScript \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a DOM. \u042d\u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 API, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a XHR \u0438\u043b\u0438 Web Storage.<\/p>\n<p><strong>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c:<\/strong> Service Worker \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0432 secure contexts, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u043e HTTPS. \u0418\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>http:\/\/localhost<\/code> \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043d\u043e \u0432 Firefox \u043c\u043e\u0436\u043d\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e HTTP \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 DevTools.<\/p>\n<p><strong>\u041c\u043e\u0434\u0443\u043b\u0438:<\/strong> Service Worker \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c JavaScript \u043c\u043e\u0434\u0443\u043b\u0438 \u2014 \u0432\u044b\u0437\u043e\u0432 <code>import()<\/code> \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443. \u041e\u0434\u043d\u0430\u043a\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b \u0447\u0435\u0440\u0435\u0437 <code>import<\/code> \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b.<\/p>\n<h3>\u0416\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b Service Worker<\/h3>\n<p>Service Worker \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u044d\u0442\u0430\u043f\u044b: <strong>\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u2192 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u2192 \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u2192 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u2192 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u2192 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a<\/strong>. \u0414\u043b\u044f push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e SW \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0444\u043e\u043d\u0435 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/p>\n<p><strong>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f Service Worker:<\/strong><\/p>\n<p>\u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f Service Worker. \u041f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0444\u0430\u0439\u043b\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0432 \u0444\u043e\u043d\u0435 \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0437\u0430\u043a\u0440\u044b\u0442\u044b. \u0414\u043b\u044f push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p>Service Worker \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442 <strong>client<\/strong> (\u043b\u044e\u0431\u0430\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, URL \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f Service Worker. \u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u044d\u0442\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b <code>WindowClient<\/code>), \u0430 \u043d\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e<\/p>\n<\/li>\n<li>\n<p>Client \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c\u044b\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0438\u043c Service Worker \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 Service Worker \u0441\u0442\u0430\u0440\u044b\u0435 client \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0440\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0434\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0432\u0441\u0435\u0445 \u0432\u043a\u043b\u0430\u0434\u043e\u043a<\/p>\n<\/li>\n<\/ul>\n<h4>2. Push API \u2014 \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438<\/h4>\n<p><strong>\u0420\u043e\u043b\u044c:<\/strong> \u0412\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0434\u043b\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a \u043d\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a<\/p>\n<\/li>\n<li>\n<p>\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 push-\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438 (FCM, Mozilla)<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b Web Push (RFC 8030)<\/p>\n<\/li>\n<li>\n<p>\u041e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 HTTP\/2 \u0438 \u044d\u043b\u043b\u0438\u043f\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 P-256<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 endpoint URL<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 push-\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 (FCM, Mozilla Push Service)<\/p>\n<\/li>\n<\/ul>\n<p>Push API \u2014 \u044d\u0442\u043e \u0432\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c push-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438\u043b\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043a\u0440\u044b\u0442\u043e.<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u044d\u0442\u043e \u043a\u0430\u043a \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0438\u0441\u0435\u043c: \u0432\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 &#171;\u043f\u0438\u0441\u044c\u043c\u043e&#187; \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0447\u0442\u043e\u0432\u0443\u044e \u0441\u043b\u0443\u0436\u0431\u0443 (push-\u0441\u0435\u0440\u0432\u0438\u0441), \u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0435\u0433\u043e \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 Service Worker \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0441\u0430\u0439\u0442 \u0437\u0430\u043a\u0440\u044b\u0442.<\/p>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h3>\n<p>Push API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c, push-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c (FCM, Mozilla Push Service) \u0438 \u0432\u0430\u0448\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c. \u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 endpoint URL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>Push API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0435 \u2014 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u044b, \u0430 Service Worker \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p>Push API \u0442\u0440\u0435\u0431\u0443\u0435\u0442 HTTPS \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b (\u043a\u0440\u043e\u043c\u0435 localhost)<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 endpoint \u0438 \u043a\u043b\u044e\u0447\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>Push-\u0441\u0435\u0440\u0432\u0438\u0441\u044b (FCM, Mozilla) \u043c\u043e\u0433\u0443\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u043e\u0442\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>Push API \u043d\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443 \u2014 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043a\u043b\u043e\u043d\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043d\u0435\u0445\u0432\u0430\u0442\u043a\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c \u0431\u0435\u0437 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430<\/p>\n<\/li>\n<\/ul>\n<h4>3. VAPID \u043a\u043b\u044e\u0447\u0438 \u2014 \u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/h4>\n<p><strong>\u0420\u043e\u043b\u044c:<\/strong> \u041a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0441\u043f\u0430\u043c\u0430 \u0438 \u0437\u043b\u043e\u0443\u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 (RFC 8291)<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u044c \u0441 \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442 RFC 8292 \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u043b\u043b\u0438\u043f\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044e P-256<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u044e\u0447\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 base64url, \u043c\u0438\u043d\u0438\u043c\u0443\u043c 65 \u0431\u0430\u0439\u0442<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 push-\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ul>\n<p>VAPID (Voluntary Application Server Identification) \u2014 \u044d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 RFC 8292, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 IETF \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 VAPID \u043a\u043b\u044e\u0447\u0438 \u043a\u0430\u043a \u043f\u0430\u0441\u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0411\u0435\u0437 \u043d\u0438\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043a\u0430\u0436\u0443\u0442\u0441\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0432\u0430\u0448\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u2014 \u043a\u0430\u043a \u043f\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u043d\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0431\u0435\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<h3>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f VAPID \u043a\u043b\u044e\u0447\u0435\u0439<\/h3>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e RFC 8292, VAPID \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044e \u043d\u0430 \u044d\u043b\u043b\u0438\u043f\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u0440\u0438\u0432\u044b\u0445 P-256. \u041a\u043b\u044e\u0447\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 base64url \u0438 \u0438\u043c\u0435\u0442\u044c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043b\u0438\u043d\u0443 65 \u0431\u0430\u0439\u0442.<\/p>\n<h3>\u0413\u0434\u0435 \u0432\u0437\u044f\u0442\u044c VAPID \u043a\u043b\u044e\u0447\u0438?<\/h3>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c npm \u043f\u0430\u043a\u0435\u0442 <code>web-push<\/code> \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c. \u042d\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f\u043c\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e VAPID \u043a\u043b\u044e\u0447\u0435\u0439.<\/p>\n<pre><code># \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 npm install -g web-push  # \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0439 web-push generate-vapid-keys  # \u0418\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 npx (\u0431\u0435\u0437 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438) npx web-push generate-vapid-keys <\/code><\/pre>\n<p><strong>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/strong><\/p>\n<pre><code>=======================================  Public Key: BO0EswuFP5ApodlzrXx85I4b_uh1C1YQggYv7wggqSksMV9qGOL_A1URE0fQ2J3eH4K0xzOGnXwQiUyXMvrjWGE  Private Key: xMd5-BGsKWo-H1n__KbNZABGsTF9x9AM8Et1qM84rR8  ======================================= <\/code><\/pre>\n<h4>4. Notifications API \u2014 \u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435<\/h4>\n<p><strong>\u0420\u043e\u043b\u044c:<\/strong> \u0412\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c\u0438 API \u041e\u0421 (Windows Action Center, macOS Notification Center)<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 secure contexts (HTTPS \u0438\u043b\u0438 localhost)<\/p>\n<\/li>\n<li>\n<p>\u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u044f\u0432\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (actions) \u0432 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p>Notifications API \u2014 \u044d\u0442\u043e \u0432\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e. \u042d\u0442\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432\u043d\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0438\u043b\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h3>\n<p>Notifications API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u0441\u043d\u0443\u044e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u043c \u0434\u0432\u0438\u0436\u043a\u043e\u043c. \u041a\u043e\u0433\u0434\u0430 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u043e\u043a\u0430\u0437 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c API \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u041e\u0421.<\/p>\n<p>\u0421 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f, Notifications API \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b: Windows Action Center, macOS Notification Center, Linux desktop notifications \u0447\u0435\u0440\u0435\u0437 D-Bus. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0432 \u0440\u043e\u043b\u0438 \u043c\u043e\u0441\u0442\u0430 \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043e\u043c \u0438 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 API \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<p>Notifications API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0435 \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u044e\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0438 \u043c\u043e\u0433\u0443\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043a\u043b\u0438\u043a\u0430, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0438\u043b\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p>Notifications API \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u044f\u0432\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0435\u0440\u0435\u0434 \u043f\u043e\u043a\u0430\u0437\u043e\u043c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043e\u0437\u0432\u0430\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u044e\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 (\u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438 \u041e\u0421)<\/p>\n<\/li>\n<li>\n<p>Notifications API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 secure contexts (HTTPS \u0438\u043b\u0438 localhost)<\/p>\n<\/li>\n<li>\n<p>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 &#171;\u041d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0438\u0442\u044c&#187;<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0438\u043b\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PWA \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c PWA \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0438 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u0435\u0437\u0434\u0435, \u0432\u043a\u043b\u044e\u0447\u0430\u044f iOS.<\/p>\n<h4>Web Application Manifest<\/h4>\n<p><strong>Web Application Manifest<\/strong> \u2014 \u044d\u0442\u043e JSON \u0444\u0430\u0439\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u2014 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0441\u0430\u0439\u0442 \u0432 Progressive Web App (PWA).<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 manifest.json<\/h3>\n<pre><code class=\"json\">{   \"short_name\": \"Push App\",   \"name\": \"Push Notifications App\",   \"description\": \"\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439\",   \"icons\": [     {       \"src\": \"\/apple-touch-icon.png\",       \"sizes\": \"180x180\",       \"type\": \"image\/png\",       \"purpose\": \"maskable\"     },     {       \"src\": \"\/nextjs-192x192.png\",       \"sizes\": \"192x192\",       \"type\": \"image\/png\",       \"purpose\": \"maskable\"     },     {       \"src\": \"\/nextjs-512x512.png\",       \"sizes\": \"512x512\",       \"type\": \"image\/png\",       \"purpose\": \"maskable\"     },     {       \"src\": \"\/favicon.ico\",       \"sizes\": \"16x16 32x32\",       \"type\": \"image\/x-icon\",       \"purpose\": \"any\"     }   ],   \"start_url\": \"\/\",   \"display\": \"standalone\",   \"theme_color\": \"#27c9b4\",   \"background_color\": \"#f4f5f7\",   \"scope\": \"\/\",   \"orientation\": \"portrait-primary\" } <\/code><\/pre>\n<h3>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0432 HTML<\/h3>\n<pre><code>&lt;!DOCTYPE html&gt; &lt;html lang=\"ru\"&gt; &lt;head&gt;     &lt;meta charset=\"UTF-8\"&gt;     &lt;meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"&gt;     &lt;title&gt;Push Notifications&lt;\/title&gt;          &lt;!-- Web App Manifest --&gt;     &lt;link rel=\"manifest\" href=\"\/manifest.json\"&gt;          &lt;!-- Meta \u0442\u0435\u0433\u0438 \u0434\u043b\u044f PWA --&gt;     &lt;meta name=\"theme-color\" content=\"#27c9b4\"&gt;     &lt;meta name=\"apple-mobile-web-app-capable\" content=\"yes\"&gt;     &lt;meta name=\"apple-mobile-web-app-status-bar-style\" content=\"black-translucent\"&gt;     &lt;meta name=\"apple-mobile-web-app-title\" content=\"Push App\"&gt;          &lt;!-- \u0418\u043a\u043e\u043d\u043a\u0438 --&gt;     &lt;link rel=\"icon\" type=\"image\/png\" href=\"\/favicon.ico\"&gt;     &lt;link rel=\"apple-touch-icon\" href=\"\/apple-touch-icon.png\"&gt; &lt;\/head&gt; &lt;body&gt;     &lt;!-- \u0412\u0430\u0448 \u043a\u043e\u043d\u0442\u0435\u043d\u0442 --&gt; &lt;\/body&gt; &lt;\/html&gt; <\/code><\/pre>\n<h3>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0434\u043b\u044f push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/h3>\n<p><code><strong>display: \"standalone\"<\/strong><\/code> \u2014 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u0432 \u043f\u043e\u043b\u043d\u043e\u044d\u043a\u0440\u0430\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 \u0431\u0435\u0437 \u0430\u0434\u0440\u0435\u0441\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430<\/p>\n<p><code><strong>scope: \"\/\"<\/strong><\/code> \u2014 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f PWA (\u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0442\u044c \u0441 scope Service Worker)<\/p>\n<p><code><strong>start_url: \"\/\"<\/strong><\/code> \u2014 URL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<p><code><strong>icons<\/strong><\/code> \u2014 \u0438\u043a\u043e\u043d\u043a\u0438 \u0434\u043b\u044f \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d (\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u043b\u044f iOS)<\/p>\n<hr\/>\n<h3>\u041e\u0442 \u0442\u0435\u043e\u0440\u0438\u0438 \u043a \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435<\/h3>\n<p>\u041f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439:<\/p>\n<ol>\n<li>\n<p><strong>Service Worker<\/strong> \u2014 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 push-\u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u0438 \u043f\u043e\u043a\u0430\u0437 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/strong> \u2014 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f Service Worker, \u0437\u0430\u043f\u0440\u043e\u0441 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439, \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u043d\u0430 push<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0435\u0440\u0432\u0435\u0440\u043d\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/strong> \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c VAPID \u043a\u043b\u044e\u0447\u0435\u0439<\/p>\n<\/li>\n<li>\n<p><strong>\u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 iOS<\/strong> \u2014 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u044b \u0438\u0445 \u043e\u0431\u0445\u043e\u0434\u0430<\/p>\n<\/li>\n<\/ol>\n<h3>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/h3>\n<p>\u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043f\u0440\u043e\u0441\u0442\u043e\u0439 web service \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<h4>Service Worker (sw.js)<\/h4>\n<pre><code class=\"javascript\">self.addEventListener('install', (event) =&gt; {   self.skipWaiting(); });  self.addEventListener('activate', (event) =&gt; {   event.waitUntil(self.clients.claim()); });  self.addEventListener('push', (event) =&gt; {   if (event.data) {     try {       const pushData = event.data.json();       self.registration.showNotification(pushData.title, pushData);     } catch (error) {       console.error('Push notification error:', error);     }   } });  self.addEventListener('notificationclick', (event) =&gt; {   event.notification.close();     event.waitUntil(     clients.openWindow('\/')     ); }); <\/code><\/pre>\n<h4>\u0420\u0430\u0437\u0431\u043e\u0440 \u043a\u043e\u0434\u0430<\/h4>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c, \u0447\u0442\u043e \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e:<\/p>\n<h3>\u0427\u0442\u043e \u0437\u0430 \u043e\u0431\u044a\u0435\u043a\u0442 self?<\/h3>\n<p><code>self<\/code> \u2014 \u044d\u0442\u043e \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0439 \u043e\u0431\u044a\u0435\u043a\u0442 \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 Service Worker, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 <code>window<\/code> \u0432 \u043e\u0431\u044b\u0447\u043d\u043e\u043c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u041e\u043d \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u0430\u043c Service Worker \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0435\u0433\u043e API.<\/p>\n<pre><code class=\"javascript\">self.addEventListener('install', (event) =&gt; {   self.skipWaiting(); }); <\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>install<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0435 \u0438\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 Service Worker. \u0412\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>self.skipWaiting()<\/code>.<\/p>\n<p><strong>\u041c\u0435\u0442\u043e\u0434 <\/strong><code><strong>skipWaiting()<\/strong><\/code> \u0437\u0430\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 Service Worker \u043d\u0435\u043c\u0435\u0434\u043b\u0435\u043d\u043d\u043e \u0441\u0442\u0430\u0442\u044c \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c, \u043c\u0438\u043d\u0443\u044f \u043e\u0431\u044b\u0447\u043d\u0443\u044e \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u0443 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u044f. \u0411\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043d\u043e\u0432\u044b\u0439 Service Worker \u0431\u0443\u0434\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d, \u043d\u043e \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u043d \u0434\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0447\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0441\u0442\u0430\u0440\u044b\u0439 Service Worker \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0438\u0442 \u043d\u043e\u0432\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438.<\/p>\n<hr\/>\n<pre><code class=\"javascript\">self.addEventListener('activate', (event) =&gt; {   event.waitUntil(self.clients.claim()); }); <\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>activate<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 Service Worker, \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c. \u0412\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>event.waitUntil(self.clients.claim())<\/code>.<\/p>\n<p><strong>\u041c\u0435\u0442\u043e\u0434 <\/strong><code><strong>self.clients.claim()<\/strong><\/code> \u0431\u0435\u0440\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u0432\u0441\u0435\u043c\u0438 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c\u0438 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0435\u0449\u0435 \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u044e\u0442\u0441\u044f Service Worker. \u0411\u0435\u0437 \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 Service Worker \u0431\u0443\u0434\u0435\u0442 \u0430\u043a\u0442\u0438\u0432\u0435\u043d, \u043d\u043e \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0438 \u2014 \u043e\u043d\u0438 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0431\u0435\u0437 Service Worker \u0434\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438.<\/p>\n<p><code>event.waitUntil()<\/code> \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e Service Worker \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d \u0434\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 <code>clients.claim()<\/code>. \u042d\u0442\u043e \u043a\u0440\u0438\u0442\u0438\u0447\u043d\u043e \u0434\u043b\u044f push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u0442\u0430\u043a \u043a\u0430\u043a Service Worker \u0434\u043e\u043b\u0436\u0435\u043d \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u0441\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e.<\/p>\n<p><strong>\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c:<\/strong> <code>waitUntil()<\/code> \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f, \u0438 Service Worker \u0431\u0443\u0434\u0435\u0442 \u0436\u0434\u0430\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u043c\u0438\u0441\u043e\u0432. \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 <code>activate<\/code> \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 Service Worker \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 (\u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0447\u0438\u0441\u0442\u043a\u0443 \u0441\u0442\u0430\u0440\u044b\u0445 \u043a\u044d\u0448\u0435\u0439) \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0442\u0438\u043f\u0430 <code>fetch<\/code> \u0438 <code>push<\/code>.<\/p>\n<hr\/>\n<pre><code class=\"javascript\">self.addEventListener('push', (event) =&gt; {   if (event.data) {     try {       const pushData = event.data.json();        \/\/ \u041f\u0440\u0438\u043c\u0435\u0440 \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u043c\u0438 \u043e\u043f\u0446\u0438\u044f\u043c\u0438       const notificationOptions = {         body: pushData.body || '\u041d\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435',         icon: pushData.icon || '\/icon-192x192.png',         badge: pushData.badge || '\/badge-72x72.png',         image: pushData.image,         tag: pushData.tag || 'default',         data: pushData.data,         requireInteraction: pushData.requireInteraction || false,         silent: pushData.silent || false,         vibrate: pushData.vibrate || [200, 100, 200],         timestamp: Date.now(),         actions: pushData.actions || []       };              self.registration.showNotification(pushData.title, notificationOptions);     } catch (error) {       console.error('Push notification error:', error);     }   } }); <\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>push<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 push-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0412\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u043b\u0438\u0447\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0441\u043e\u0431\u044b\u0442\u0438\u0438.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442, \u043a\u043e\u0434 \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u044c \u0438\u0445 \u043a\u0430\u043a JSON \u0447\u0435\u0440\u0435\u0437 <code>event.data.json()<\/code>. \u0417\u0430\u0442\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 <code>notificationOptions<\/code> \u0441 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0432\u043a\u043b\u044e\u0447\u0430\u044f fallback \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0445 \u043e\u043f\u0446\u0438\u0439. \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 <code>showNotification()<\/code><\/p>\n<p><strong>\u041c\u0435\u0442\u043e\u0434 <\/strong><code><strong>showNotification()<\/strong><\/code> \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0441 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c \u0438 \u043e\u043f\u0446\u0438\u044f\u043c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u0438\u043a\u043e\u043d\u043a\u0443, \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u0432\u0438\u0431\u0440\u0430\u0446\u0438\u044e \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b.<\/p>\n<p><strong>\u0413\u0438\u0431\u043a\u043e\u0441\u0442\u044c \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438:<\/strong> <code>showNotification()<\/code> \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u043e\u043f\u0446\u0438\u0439 \u0434\u043b\u044f \u043a\u0430\u0441\u0442\u043e\u043c\u0438\u0437\u0430\u0446\u0438\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439:<\/p>\n<ul>\n<li>\n<p><code><strong>body<\/strong><\/code> \u2014 \u0442\u0435\u043a\u0441\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u043e\u0434 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u043c<\/p>\n<\/li>\n<li>\n<p><code><strong>icon<\/strong><\/code> \u2014 URL \u0438\u043a\u043e\u043d\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><code><strong>image<\/strong><\/code> \u2014 URL \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code><strong>badge<\/strong><\/code> \u2014 \u0438\u043a\u043e\u043d\u043a\u0430 \u0434\u043b\u044f \u043f\u0430\u043d\u0435\u043b\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 (Android)<\/p>\n<\/li>\n<li>\n<p><code><strong>tag<\/strong><\/code> \u2014 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0434\u043b\u044f \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u043e\u0432\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p><code><strong>data<\/strong><\/code> \u2014 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0438 \u0432 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043b\u0438\u043a\u0430<\/p>\n<\/li>\n<li>\n<p><code><strong>actions<\/strong><\/code> \u2014 \u043c\u0430\u0441\u0441\u0438\u0432 \u043a\u043d\u043e\u043f\u043e\u043a \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 (\u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e)<\/p>\n<\/li>\n<li>\n<p><code><strong>requireInteraction<\/strong><\/code> \u2014 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><code><strong>silent<\/strong><\/code> \u2014 \u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0437\u0432\u0443\u043a\u0430 \u0438 \u0432\u0438\u0431\u0440\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code><strong>vibrate<\/strong><\/code> \u2014 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u0432\u0438\u0431\u0440\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p><code><strong>timestamp<\/strong><\/code> \u2014 \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><code><strong>dir<\/strong><\/code> \u2014 \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0435\u043a\u0441\u0442\u0430 (ltr\/rtl)<\/p>\n<\/li>\n<li>\n<p><code><strong>lang<\/strong><\/code> \u2014 \u044f\u0437\u044b\u043a \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p><code><strong>renotify<\/strong><\/code> \u2014 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u0437\u0430\u043c\u0435\u043d\u0435<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c:<\/strong> <code>showNotification()<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u0440\u043e\u043c\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u0432 <code>undefined<\/code> \u043f\u0440\u0438 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u043c \u043f\u043e\u043a\u0430\u0437\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f. \u0415\u0441\u043b\u0438 Service Worker \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u0435\u043d \u0438\u043b\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043f\u0440\u0435\u0442\u0438\u043b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u043c\u0435\u0442\u043e\u0434 \u0432\u044b\u0431\u0440\u043e\u0441\u0438\u0442 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 <code>TypeError<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0430\u0436\u043d\u043e \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 <code>try\/catch<\/code>.<\/p>\n<hr\/>\n<pre><code class=\"javascript\">self.addEventListener('notificationclick', (event) =&gt; {   event.notification.close();    \/\/\u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0433\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0438\u043b\u0438 \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u0441\u044f \u043d\u0430 \u043e\u0442\u0432\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430   const url = event.notification.data?.url || '\/';    event.waitUntil(     clients.openWindow(url)   ); }); <\/code><\/pre>\n<p>\u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u044f <code>notificationclick<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u043f\u0440\u0438 \u043a\u043b\u0438\u043a\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u043e push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044e. \u0412\u043d\u0443\u0442\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f <code>event.notification.close()<\/code> \u0434\u043b\u044f \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p><strong>\u041c\u0435\u0442\u043e\u0434 <\/strong><code><strong>close()<\/strong><\/code> \u0443\u0434\u0430\u043b\u044f\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0441 \u044d\u043a\u0440\u0430\u043d\u0430 \u0438 \u0438\u0437 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0433\u043e \u0442\u0440\u0435\u044f \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439. \u042d\u0442\u043e \u0432\u0430\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043b\u0435 \u043a\u043b\u0438\u043a\u0430, \u0447\u0442\u043e\u0431\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043d\u0435 \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u0432\u0438\u0434\u0438\u043c\u044b\u043c \u043f\u043e\u0441\u043b\u0435 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0443\u0436\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u043b \u0441 \u043d\u0438\u043c.<\/p>\n<p>\u0417\u0430\u0442\u0435\u043c \u043a\u043e\u0434 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u0435\u0442 URL \u0438\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f (<code>event.notification.data?.url<\/code>) \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0434\u0435\u0444\u043e\u043b\u0442\u043d\u044b\u0439 \u043f\u0443\u0442\u044c <code>'\/'<\/code>. \u042d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438 \u0432 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f\u0445. \u041c\u0435\u0442\u043e\u0434 <code>openWindow()<\/code> \u043e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u043d\u043e\u0432\u0443\u044e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0441 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u044b\u043c URL.<\/p>\n<p><strong>\u041f\u0440\u043e <\/strong><code><strong>event.waitUntil()<\/strong><\/code> \u043c\u044b \u0443\u0436\u0435 \u0437\u043d\u0430\u0435\u043c \u2014 \u043e\u043d \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442, \u0447\u0442\u043e Service Worker \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d \u0434\u043e \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438.<\/p>\n<hr\/>\n<h3>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0430\u044f \u0447\u0430\u0441\u0442\u044c<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0443\u044e \u0447\u0430\u0441\u0442\u044c \u0434\u043b\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043d\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f. \u042d\u0442\u043e\u0442 \u043a\u043e\u0434 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u043c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043e\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<h4>client.js<\/h4>\n<pre><code class=\"javascript\">const vapidPublicKey = `BO0EswuFP5ApodlzrXx85I4b_uh1C1YQggYv7wggqSksMV9qGOL_A1URE0fQ2J3eH4K0xzOGnXwQiUyXMvrjWGE`;  function urlBase64ToUint8Array(base64String) {   const padding = '='.repeat((4 - (base64String.length % 4)) % 4);   const base64 = (base64String + padding).replace(\/-\/g, '+').replace(\/_\/g, '\/');    const rawData = window.atob(base64);   const outputArray = new Uint8Array(rawData.length);    for (let i = 0; i &lt; rawData.length; ++i) {     outputArray[i] = rawData.charCodeAt(i);   }   return outputArray; }  function isPushManagerActive(pushManager) {   if (!pushManager) {     console.warn('PushManager is not available');     return false;   }   return true; }  async function initServiceWorker() {   try {     const swRegistration = await navigator.serviceWorker.register('\/sw.js', {       scope: '\/',     });      const pushManager = swRegistration.pushManager;      if (!isPushManagerActive(pushManager)) {       return;     }      const permissionState = await pushManager.permissionState({ userVisibleOnly: true });      switch (permissionState) {       case 'prompt': \/\/ \u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u043a\u0430 \u043d\u0435 \u0434\u0430\u043d\u043e         return 'prompt';       case 'granted': { \/\/ \u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043e         const existingSubscription = await pushManager.getSubscription();         if (existingSubscription) {           await sendSubscriptionToServer(existingSubscription);         }         return 'granted';       }       case 'denied': \/\/ \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043e\u0442\u043a\u0430\u0437\u0430\u043b \u0432 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0438 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439         return 'denied';     }   } catch (error) {     console.error('Service Worker initialization error:', error);     return 'error';   } }  async function subscribeToPush() {   if (!vapidPublicKey) {     console.error('VAPID key is not configured');     return;   }    try {     const swRegistration = await navigator.serviceWorker.ready;     const pushManager = swRegistration.pushManager;      if (!isPushManagerActive(pushManager)) {       return;     }      const subscriptionOptions = {       userVisibleOnly: true,       applicationServerKey: urlBase64ToUint8Array(vapidPublicKey),     };      const subscription = await pushManager.subscribe(subscriptionOptions);          await sendSubscriptionToServer(subscription);     return true;   } catch (error) {     console.error('Push subscription error:', error);     return false;   } }  async function sendSubscriptionToServer(subscription) {   try {     const subscriptionJson = subscription.toJSON();      if (!subscriptionJson.keys?.p256dh || !subscriptionJson.keys?.auth || !subscriptionJson.endpoint) {       throw new Error('\u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438');     }      const subscriptionInfo = {       endpoint: subscription.endpoint,       keys: {         p256dh: subscriptionJson.keys.p256dh,         auth: subscriptionJson.keys.auth,       },     };      const response = await fetch('\/web-push', {       method: 'POST',       headers: {         'Content-Type': 'application\/json',       },       body: JSON.stringify(subscriptionInfo),     });        } catch (error) {     console.error('Server subscription error:', error);     throw error;   } }    \/\/ \u0417\u0430\u043f\u0443\u0441\u043a \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b if (navigator.serviceWorker &amp;&amp; 'PushManager' in window) {   initServiceWorker().then((state) =&gt; {     if (state === 'prompt') {       \/\/ \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c UI \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438 \u043d\u0430\u0436\u0430\u0442\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043d\u0430\u0448\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e `subscribeToPush()`     }   }); } else {   console.warn('Push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u044d\u0442\u043e\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435'); }  <\/code><\/pre>\n<h4>\u0420\u0430\u0437\u0431\u043e\u0440 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430<\/h4>\n<h3>\u041e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438<\/h3>\n<p><code><strong>urlBase64ToUint8Array()<\/strong><\/code> \u2014 \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u0443\u0435\u0442 VAPID \u043a\u043b\u044e\u0447 \u0438\u0437 base64 \u0432 Uint8Array \u0444\u043e\u0440\u043c\u0430\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 Push API.<\/p>\n<p><code><strong>isPushManagerActive()<\/strong><\/code> \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e\u0441\u0442\u044c PushManager \u0432 Service Worker. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 <code>true<\/code> \u0435\u0441\u043b\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, <code>false<\/code> \u0435\u0441\u043b\u0438 \u043d\u0435\u0442.<\/p>\n<p><code><strong>initServiceWorker()<\/strong><\/code> \u2014 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 Service Worker \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442: <code>'prompt'<\/code>, <code>'granted'<\/code>, <code>'denied'<\/code> \u0438\u043b\u0438 <code>'error'<\/code>.<\/p>\n<p><code><strong>subscribeToPush()<\/strong><\/code> \u2014 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u043d\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c VAPID \u043a\u043b\u044e\u0447\u0430.<\/p>\n<p><code><strong>sendSubscriptionToServer()<\/strong><\/code> \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440 \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f.<\/p>\n<h3>\u041a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u043c\u0435\u0442\u043e\u0434\u044b<\/h3>\n<p><code><strong>navigator.serviceWorker.register('\/sw.js', { scope: '\/' })<\/strong><\/code> \u2014 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 Service Worker <em>\u0414\u041b\u042f \u0412\u0421\u0415\u0413\u041e \u0421\u0410\u0419\u0422\u0410<\/em>.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u043e:<\/strong> Service Worker \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u0441\u0430\u0439\u0442\u0430, \u043d\u043e \u0438 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u043f\u0443\u0442\u0435\u0439:<\/p>\n<pre><code class=\"javascript\">\/\/ \u0414\u043b\u044f \u0432\u0441\u0435\u0433\u043e \u0441\u0430\u0439\u0442\u0430 navigator.serviceWorker.register('\/sw.js', { scope: '\/' });  \/\/ \u0414\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u0430\u043f\u043a\u0438 navigator.serviceWorker.register('\/sw.js', { scope: '\/admin\/' });  \/\/ \u0414\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b navigator.serviceWorker.register('\/sw.js', { scope: '\/dashboard' });  \/\/ \u0411\u0435\u0437 scope (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e - \u043f\u0430\u043f\u043a\u0430 \u0433\u0434\u0435 \u043b\u0435\u0436\u0438\u0442 sw.js) navigator.serviceWorker.register('\/admin\/sw.js'); \/\/ scope \u0431\u0443\u0434\u0435\u0442 '\/admin\/' <\/code><\/pre>\n<p><code><strong>pushManager.permissionState({ userVisibleOnly: true })<\/strong><\/code> \u2014 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u043d\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<p><code><strong>pushManager.subscribe(subscriptionOptions)<\/strong><\/code> \u2014 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443. \u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (\u043a\u043b\u0438\u043a). (\u041c\u043e\u0436\u043d\u043e \u0438 \u0431\u0435\u0437 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f, \u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0435 \u0432\u043e \u0432\u0441\u0435\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445)<\/p>\n<p><code><strong>navigator.serviceWorker.ready<\/strong><\/code> \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 Promise, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0433\u0434\u0430 Service Worker \u0430\u043a\u0442\u0438\u0432\u0435\u043d. Promise \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u0435\u0442\u0441\u044f, \u0442\u043e\u043b\u044c\u043a\u043e \u0436\u0434\u0435\u0442 \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u0438. \u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0434 <code>pushManager.subscribe()<\/code>.<\/p>\n<h3>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438<\/h3>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0443\u0441\u043f\u0435\u0448\u043d\u043e\u0439 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 <code>pushManager.subscribe()<\/code> \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c\u0438 endpoint&#8217;\u0430\u043c\u0438 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430:<\/p>\n<p><strong>Desktop (Firefox):<\/strong><\/p>\n<pre><code class=\"javascript\">{   endpoint: \"https:\/\/updates.push.services.mozilla.com\/wpush\/v2\/...\",   keys: {     p256dh: \"BEl62iUYgUivxIkv69yViEuiBIa40HI...\",     auth: \"tBHItJI5svbpez7KI4CCXg==\"   },   expirationTime: 1640995200000 } <\/code><\/pre>\n<p><strong>Mobile (Android Chrome):<\/strong><\/p>\n<pre><code class=\"javascript\">{   endpoint: \"https:\/\/fcm.googleapis.com\/fcm\/send\/...\",   keys: {     p256dh: \"BEl62iUYgUivxIkv69yViEuiBIa40HI...\",     auth: \"tBHItJI5svbpez7KI4CCXg==\"   },   expirationTime: null } <\/code><\/pre>\n<p><strong>Mobile (iOS Safari 16.4+):<\/strong><\/p>\n<pre><code class=\"javascript\">{   endpoint: \"https:\/\/web.push.apple.com\/...\",   keys: {     p256dh: \"BEl62iUYgUivxIkv69yViEuiBIa40HI...\",     auth: \"tBHItJI5svbpez7KI4CCXg==\"   },   expirationTime: null } <\/code><\/pre>\n<p><strong>Desktop (Microsoft Edge):<\/strong><\/p>\n<pre><code class=\"javascript\">{   endpoint: \"https:\/\/wns2-wns2p.notify.windows.com\/...\",   keys: {     p256dh: \"BEl62iUYgUivxIkv69yViEuiBIa40HI...\",     auth: \"tBHItJI5svbpez7KI4CCXg==\"   },   expirationTime: null } <\/code><\/pre>\n<h3>\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 backend \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 express<\/h3>\n<pre><code class=\"javascript\">const express = require('express'); const webpush = require('web-push');  const app = express(); app.use(express.json());  \/\/ VAPID \u043a\u043b\u044e\u0447\u0438 (\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u0441\u0432\u043e\u0438) const VAPID_PUBLIC_KEY = \"BO0EswuFP5ApodlzrXx85I4b_uh1C1YQggYv7wggqSksMV9qGOL_A1URE0fQ2J3eH4K0xzOGnXwQiUyXMvrjWGE\"; const VAPID_PRIVATE_KEY = \"xMd5-BGsKWo-H1n__KbNZABGsTF9x9AM8Et1qM84rR8\";  \/\/ \u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 VAPID webpush.setVapidDetails(     'mailto:your-email@example.com',     VAPID_PUBLIC_KEY,     VAPID_PRIVATE_KEY );  \/\/ \u041f\u0440\u0438\u043c\u0435\u0440 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a const subscriptions = [];  \/\/ \u0421\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 app.post('\/web-push', (req, res) =&gt; {     const subscription = req.body;     subscriptions.push(subscription);     res.status(201).json({ success: true }); });  \/\/ \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f function sendNotification(title, body, icon) {     const payload = JSON.stringify({         title: title || '\u041d\u043e\u0432\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435',         body: body || '\u0423 \u0432\u0430\u0441 \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435',         icon: icon || '\/icon.png',         data: { url: '\/' }     });      return webpush.sendNotification(subscriptions[0], payload); }  \/\/ \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f sendNotification('\u041f\u0440\u0438\u0432\u0435\u0442!', '\u042d\u0442\u043e \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435', '\/icon.png')     .then(() =&gt; console.log('Notification sent'))     .catch(err =&gt; console.error('Error:', err));  app.listen(3000, () =&gt; {     console.log('Server running on port 3000'); }); <\/code><\/pre>\n<h3>\u0413\u043e\u0442\u043e\u0432\u043e! Push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432\u0435\u0437\u0434\u0435 \ud83c\udf89<\/h3>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0430\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u0445 \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430\u0445 \u2014 \u0434\u0430\u0436\u0435 \u043d\u0430 iOS!<\/p>\n<p><strong>\u041a\u0430\u043a \u0442\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c?<\/strong> \u0415\u0449\u0435 \u043d\u0435\u0434\u0430\u0432\u043d\u043e iOS \u0431\u044b\u043b \u0433\u043b\u0430\u0432\u043d\u043e\u0439 \u0433\u043e\u043b\u043e\u0432\u043d\u043e\u0439 \u0431\u043e\u043b\u044c\u044e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432, \u043d\u043e Apple \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u0441\u0434\u0430\u043b\u0430\u0441\u044c. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c.<\/p>\n<h3>\u0418\u0441\u0442\u043e\u0440\u0438\u044f Service Worker \u043d\u0430 iOS<\/h3>\n<h4>\u0425\u0440\u043e\u043d\u043e\u043b\u043e\u0433\u0438\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438<\/h4>\n<p><strong>iOS 11.3 (\u043c\u0430\u0440\u0442 2018)<\/strong> \u2014 Apple \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0430 \u0431\u0430\u0437\u043e\u0432\u0443\u044e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 Service Worker, \u043d\u043e \u0441 \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u044b\u043c\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>Service Worker \u0440\u0430\u0431\u043e\u0442\u0430\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Safari<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u043b push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c<\/p>\n<\/li>\n<\/ul>\n<p><strong>iOS 16.4 (\u043c\u0430\u0440\u0442 2023)<\/strong> \u2014 \u0440\u0435\u0432\u043e\u043b\u044e\u0446\u0438\u043e\u043d\u043d\u043e\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435:<\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u043d\u0430\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0432 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0447\u0435\u0440\u0435\u0437 Apple Push Notification service (APNs)<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 VAPID \u043a\u043b\u044e\u0447\u0435\u0439<\/p>\n<\/li>\n<\/ul>\n<h4>\u0423\u0441\u043b\u043e\u0432\u0438\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430 iOS<\/h4>\n<p><strong>1. \u0412\u0435\u0440\u0441\u0438\u044f iOS 16.4+<\/strong><\/p>\n<ul>\n<li>\n<p>\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0434\u043b\u044f push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0421\u0442\u0430\u0440\u044b\u0435 \u0432\u0435\u0440\u0441\u0438\u0438 iOS \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 web push<\/p>\n<\/li>\n<\/ul>\n<p><strong>2. PWA (Progressive Web App)<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u043e \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u044b\u0447\u043d\u044b\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0438 Safari \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u0422\u043e\u043b\u044c\u043a\u043e standalone \u0440\u0435\u0436\u0438\u043c (\u0432\u043d\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430)<\/p>\n<\/li>\n<\/ul>\n<p><strong>3. HTTPS \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e<\/strong><\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 secure contexts<\/p>\n<\/li>\n<li>\n<p>HTTP \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f (\u043a\u0440\u043e\u043c\u0435 localhost \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438)<\/p>\n<\/li>\n<\/ul>\n<p><strong>4. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/strong><\/p>\n<ul>\n<li>\n<p>\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u043b\u044c\u0437\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0431\u0435\u0437 \u0441\u043e\u0433\u043b\u0430\u0441\u0438\u044f<\/p>\n<\/li>\n<\/ul>\n<h4>\u0414\u0435\u0442\u0435\u043a\u0446\u0438\u044f iOS \u0438 \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 PWA<\/h4>\n<p>\u0425\u043e\u0442\u044f \u043c\u044b \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043b\u0438 PWA \u0438 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043d\u0430 iOS, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u0443\u0442 \u043d\u0435 \u0437\u043d\u0430\u0442\u044c, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043a\u0440\u0430\u043d. \u042d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043d\u0430\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c, \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f \u043b\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f iOS \u043d\u0430 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f, \u0438 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f.<\/p>\n<pre><code class=\"javascript\">function checkIOSAndPWA() {   const isIOS = \/iPad|iPhone|iPod\/.test(navigator.userAgent);   const isPWA = window.matchMedia('(display-mode: standalone)').matches ||                 window.navigator.standalone === true;      if (isIOS &amp;&amp; !isPWA) {     console.log(\"\u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b push \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u0441\u0442\u043e\u043b\")   } } <\/code><\/pre>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041c\u044b \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438 \u043f\u043e\u043b\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0432 PWA \u0431\u0435\u0437 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u043e\u0440\u043e\u043d\u043d\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u0432\u0430\u0441 \u0435\u0441\u0442\u044c:<\/p>\n<p>\u2705 <strong>\u041f\u043e\u043b\u043d\u043e\u0435 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b<\/strong> \u2014 Service Worker, Push API, VAPID \u043a\u043b\u044e\u0447\u0438 \u0438 Notifications API<br \/> \u2705 <strong>\u0413\u043e\u0442\u043e\u0432\u044b\u0439 \u043a\u043e\u0434<\/strong> \u2014 \u043e\u0442 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 Service Worker \u0434\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<br \/> \u2705 <strong>PWA \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430<\/strong> \u2014 manifest.json \u0438 HTML \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445<br \/> \u2705 <strong>iOS \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430<\/strong> \u2014 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439 \u0438 \u0441\u043f\u043e\u0441\u043e\u0431\u043e\u0432 \u0438\u0445 \u043e\u0431\u0445\u043e\u0434\u0430<\/p>\n<p><strong>\u0413\u043b\u0430\u0432\u043d\u044b\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e<\/p>\n<\/li>\n<li>\n<p>\u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0435\u0439<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435\u0445 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445<\/p>\n<\/li>\n<li>\n<p>\u0411\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e \u0438 \u0431\u0435\u0437 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<\/ul>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u043b\u044e\u0431\u043e\u043c \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438, \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0432 \u0435\u0433\u043e \u0432 \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u0443\u044e PWA \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/945870\/\"> https:\/\/habr.com\/ru\/articles\/945870\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<blockquote>\n<p><strong>Service Worker + Push API + VAPID \u043a\u043b\u044e\u0447\u0438 + Notifications API = \u043f\u043e\u043b\u043d\u043e\u0446\u0435\u043d\u043d\u044b\u0435 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/strong> \u041d\u0438\u043a\u0430\u043a\u0438\u0445 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043f\u043e\u043b\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044c \u043d\u0430\u0434 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<\/blockquote>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439, \u0432\u0435\u0431-push \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438, \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043d\u0430 \u0432\u0441\u0435\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0430\u0445. \u0415\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u2014 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 iOS, \u0433\u0434\u0435 Apple \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 2023 \u0433\u043e\u0434\u0443.<\/p>\n<h3>\u0410\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/h3>\n<p>\u0421\u0438\u0441\u0442\u0435\u043c\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u2014 \u044d\u0442\u043e \u0441\u043b\u043e\u0436\u043d\u0430\u044f \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0438\u0437 \u0447\u0435\u0442\u044b\u0440\u0435\u0445 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. \u041e\u043d\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0432\u043c\u0435\u0441\u0442\u0435, \u0447\u0442\u043e\u0431\u044b \u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043e\u0442 \u0432\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0434\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f. \u041a\u0430\u0436\u0434\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0437\u0430 \u0441\u0432\u043e\u044e \u0447\u0430\u0441\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430, \u043d\u043e \u0431\u0435\u0437 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442.<\/p>\n<h4>\u041e\u0431\u0449\u0438\u0439 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0440\u0430\u0431\u043e\u0442\u044b<\/h4>\n<ol>\n<li>\n<p><strong>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c<\/strong> \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0440\u0430\u0443\u0437\u0435\u0440<\/strong> \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0443\u044e \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u0441 \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u043a\u043b\u044e\u0447\u0430\u043c\u0438<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0435\u0440\u0432\u0435\u0440<\/strong> \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u0437\u0430\u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0447\u0435\u0440\u0435\u0437 push-\u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430 \u044d\u0442\u0443 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443<\/p>\n<\/li>\n<li>\n<p><strong>Push-\u0441\u0435\u0440\u0432\u0438\u0441<\/strong> \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p><strong>Service Worker<\/strong> \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0435\u0433\u043e<\/p>\n<\/li>\n<li>\n<p><strong>Notifications API<\/strong> \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e<\/p>\n<\/li>\n<\/ol>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u0438 \u043f\u043e\u0439\u043c\u0435\u043c, \u043a\u0442\u043e \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442 \u0438 \u0437\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442.<\/p>\n<h4>1. Service Worker \u2014 \u0424\u043e\u043d\u043e\u0432\u044b\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a<\/h4>\n<p><strong>\u0420\u043e\u043b\u044c:<\/strong> JavaScript-\u0441\u043a\u0440\u0438\u043f\u0442, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0432 \u0444\u043e\u043d\u0435 \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 push-\u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/p>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 push-\u0441\u043e\u0431\u044b\u0442\u0438\u0439 \u043e\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043a\u0430\u0437 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 Notifications API<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430 \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u041d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a DOM<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0422\u0440\u0435\u0431\u0443\u0435\u0442 HTTPS \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b (\u043a\u0440\u043e\u043c\u0435 localhost)<\/p>\n<\/li>\n<\/ul>\n<p>Service Worker \u2014 \u044d\u0442\u043e \u0442\u0438\u043f web worker, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043a\u0430\u043a \u043f\u0440\u043e\u043a\u0441\u0438-\u0441\u0435\u0440\u0432\u0435\u0440 \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438, \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c \u0438 \u0441\u0435\u0442\u044c\u044e. Service Worker \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 (scope), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f origin (\u0434\u043e\u043c\u0435\u043d + \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b + \u043f\u043e\u0440\u0442) \u0438 \u043f\u0443\u0442\u0435\u043c.<\/p>\n<p><strong>\u041f\u0440\u043e\u0441\u0442\u044b\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438:<\/strong> Service Worker \u2014 \u044d\u0442\u043e JavaScript \u0441\u043a\u0440\u0438\u043f\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0444\u043e\u043d\u0435 \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043a\u0440\u044b\u043b \u0431\u0440\u0430\u0443\u0437\u0435\u0440. \u041e\u043d \u043c\u043e\u0436\u0435\u0442 \u043f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0441\u0435\u0442\u0435\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u044b \u0438 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f.<\/p>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h3>\n<p>Service Worker \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 \u043e\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e JavaScript \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0438 \u043d\u0435 \u0438\u043c\u0435\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a DOM. \u042d\u0442\u043e \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0435 API, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a XHR \u0438\u043b\u0438 Web Storage.<\/p>\n<p><strong>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c:<\/strong> Service Worker \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0432 secure contexts, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u043e HTTPS. \u0418\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 <code>http:\/\/localhost<\/code> \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043d\u043e \u0432 Firefox \u043c\u043e\u0436\u043d\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e HTTP \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 DevTools.<\/p>\n<p><strong>\u041c\u043e\u0434\u0443\u043b\u0438:<\/strong> Service Worker \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0438\u043c\u043f\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c JavaScript \u043c\u043e\u0434\u0443\u043b\u0438 \u2014 \u0432\u044b\u0437\u043e\u0432 <code>import()<\/code> \u0432 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0438\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u043e\u0448\u0438\u0431\u043a\u0443. \u041e\u0434\u043d\u0430\u043a\u043e \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u043c\u043f\u043e\u0440\u0442\u044b \u0447\u0435\u0440\u0435\u0437 <code>import<\/code> \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u044b.<\/p>\n<h3>\u0416\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b Service Worker<\/h3>\n<p>Service Worker \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u044d\u0442\u0430\u043f\u044b: <strong>\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u2192 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u2192 \u0430\u043a\u0442\u0438\u0432\u0430\u0446\u0438\u044f \u2192 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u2192 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u2192 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a<\/strong>. \u0414\u043b\u044f push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u0432\u0430\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c, \u0447\u0442\u043e SW \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0432 \u0444\u043e\u043d\u0435 \u0438 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0434\u0430\u0436\u0435 \u043f\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u043c \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/p>\n<p><strong>\u041e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f Service Worker:<\/strong><\/p>\n<p>\u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f Service Worker. \u041f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0444\u0430\u0439\u043b\u0430 \u043d\u043e\u0432\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u0432 \u0444\u043e\u043d\u0435 \u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u0437\u0430\u043a\u0440\u044b\u0442\u044b. \u0414\u043b\u044f push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u044d\u0442\u043e \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u044e\u0442 \u0440\u0430\u0431\u043e\u0442\u0443 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p>Service Worker \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u0442 <strong>client<\/strong> (\u043b\u044e\u0431\u0430\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430, URL \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f Service Worker. \u041a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e \u044d\u0442\u043e \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b <code>WindowClient<\/code>), \u0430 \u043d\u0435 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u044b \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e<\/p>\n<\/li>\n<li>\n<p>Client \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c\u044b\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u0438\u043c Service Worker \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 Service Worker \u0441\u0442\u0430\u0440\u044b\u0435 client \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u044e\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0430\u0440\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0434\u043e \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0432\u0441\u0435\u0445 \u0432\u043a\u043b\u0430\u0434\u043e\u043a<\/p>\n<\/li>\n<\/ul>\n<h4>2. Push API \u2014 \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438<\/h4>\n<p><strong>\u0420\u043e\u043b\u044c:<\/strong> \u0412\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0434\u043b\u044f \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0439 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a \u043d\u0430 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<li>\n<p>\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u043c \u0446\u0438\u043a\u043b\u043e\u043c \u043f\u043e\u0434\u043f\u0438\u0441\u043e\u043a<\/p>\n<\/li>\n<li>\n<p>\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 push-\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438 (FCM, Mozilla)<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b Web Push (RFC 8030)<\/p>\n<\/li>\n<li>\n<p>\u041e\u0441\u043d\u043e\u0432\u0430\u043d \u043d\u0430 HTTP\/2 \u0438 \u044d\u043b\u043b\u0438\u043f\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 P-256<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 endpoint URL<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 push-\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432 (FCM, Mozilla Push Service)<\/p>\n<\/li>\n<\/ul>\n<p>Push API \u2014 \u044d\u0442\u043e \u0432\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c push-\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043e\u0442 \u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435 \u0438\u043b\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u043a\u0440\u044b\u0442\u043e.<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 \u044d\u0442\u043e \u043a\u0430\u043a \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u043f\u0438\u0441\u0435\u043c: \u0432\u0430\u0448 \u0441\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 &#171;\u043f\u0438\u0441\u044c\u043c\u043e&#187; \u0447\u0435\u0440\u0435\u0437 \u043f\u043e\u0447\u0442\u043e\u0432\u0443\u044e \u0441\u043b\u0443\u0436\u0431\u0443 (push-\u0441\u0435\u0440\u0432\u0438\u0441), \u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0435\u0433\u043e \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 Service Worker \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438. \u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435, \u0434\u0430\u0436\u0435 \u0435\u0441\u043b\u0438 \u0441\u0430\u0439\u0442 \u0437\u0430\u043a\u0440\u044b\u0442.<\/p>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h3>\n<p>Push API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c, push-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c (FCM, Mozilla Push Service) \u0438 \u0432\u0430\u0448\u0438\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u043e\u043c. \u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 endpoint URL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u0434\u043b\u044f \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0438 \u0448\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<p>Push API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0435 \u2014 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 \u0432\u043a\u043b\u0430\u0434\u043a\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u044b, \u0430 Service Worker \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p>Push API \u0442\u0440\u0435\u0431\u0443\u0435\u0442 HTTPS \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b (\u043a\u0440\u043e\u043c\u0435 localhost)<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u0430\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430 \u0438\u043c\u0435\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 endpoint \u0438 \u043a\u043b\u044e\u0447\u0438 \u0430\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>Push-\u0441\u0435\u0440\u0432\u0438\u0441\u044b (FCM, Mozilla) \u043c\u043e\u0433\u0443\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0447\u0430\u0441\u0442\u043e\u0442\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>Push API \u043d\u0435 \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u0434\u043e\u0441\u0442\u0430\u0432\u043a\u0443 \u2014 \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043a\u043b\u043e\u043d\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u0438 \u043d\u0435\u0445\u0432\u0430\u0442\u043a\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u043f\u0438\u0441\u043a\u0438 \u043c\u043e\u0433\u0443\u0442 \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u043c \u0431\u0435\u0437 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430<\/p>\n<\/li>\n<\/ul>\n<h4>3. VAPID \u043a\u043b\u044e\u0447\u0438 \u2014 \u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/h4>\n<p><strong>\u0420\u043e\u043b\u044c:<\/strong> \u041a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u041f\u0440\u0435\u0434\u043e\u0442\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0441\u043f\u0430\u043c\u0430 \u0438 \u0437\u043b\u043e\u0443\u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0428\u0438\u0444\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 (RFC 8291)<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u044f\u0437\u044c \u0441 \u0432\u043b\u0430\u0434\u0435\u043b\u044c\u0446\u0435\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442 RFC 8292 \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u044d\u043b\u043b\u0438\u043f\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044e P-256<\/p>\n<\/li>\n<li>\n<p>\u041a\u043b\u044e\u0447\u0438 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 base64url, \u043c\u0438\u043d\u0438\u043c\u0443\u043c 65 \u0431\u0430\u0439\u0442<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 push-\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438<\/p>\n<\/li>\n<\/ul>\n<p>VAPID (Voluntary Application Server Identification) \u2014 \u044d\u0442\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 RFC 8292, \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0439 IETF \u0434\u043b\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043f\u0440\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439.<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u044c\u0442\u0435 VAPID \u043a\u043b\u044e\u0447\u0438 \u043a\u0430\u043a \u043f\u0430\u0441\u043f\u043e\u0440\u0442 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0411\u0435\u0437 \u043d\u0438\u0445 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0442\u043a\u0430\u0436\u0443\u0442\u0441\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u0432\u0430\u0448\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u2014 \u043a\u0430\u043a \u043f\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u043d\u0438\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0431\u0435\u0437 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<h3>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f VAPID \u043a\u043b\u044e\u0447\u0435\u0439<\/h3>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e RFC 8292, VAPID \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u044e \u043d\u0430 \u044d\u043b\u043b\u0438\u043f\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043a\u0440\u0438\u0432\u044b\u0445 P-256. \u041a\u043b\u044e\u0447\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 base64url \u0438 \u0438\u043c\u0435\u0442\u044c \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0443\u044e \u0434\u043b\u0438\u043d\u0443 65 \u0431\u0430\u0439\u0442.<\/p>\n<h3>\u0413\u0434\u0435 \u0432\u0437\u044f\u0442\u044c VAPID \u043a\u043b\u044e\u0447\u0438?<\/h3>\n<p>\u0421\u0430\u043c\u044b\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0438 \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c npm \u043f\u0430\u043a\u0435\u0442 <code>web-push<\/code> \u0441 \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c. \u042d\u0442\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u0441\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f\u043c\u0438, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044e VAPID \u043a\u043b\u044e\u0447\u0435\u0439.<\/p>\n<pre><code># \u0423\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 npm install -g web-push  # \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043a\u043b\u044e\u0447\u0435\u0439 web-push generate-vapid-keys  # \u0418\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 npx (\u0431\u0435\u0437 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438) npx web-push generate-vapid-keys <\/code><\/pre>\n<p><strong>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442:<\/strong><\/p>\n<pre><code>=======================================  Public Key: BO0EswuFP5ApodlzrXx85I4b_uh1C1YQggYv7wggqSksMV9qGOL_A1URE0fQ2J3eH4K0xzOGnXwQiUyXMvrjWGE  Private Key: xMd5-BGsKWo-H1n__KbNZABGsTF9x9AM8Et1qM84rR8  ======================================= <\/code><\/pre>\n<h4>4. Notifications API \u2014 \u041e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435<\/h4>\n<p><strong>\u0420\u043e\u043b\u044c:<\/strong> \u0412\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442 \u0434\u043b\u044f \u043f\u043e\u043a\u0430\u0437\u0430 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<p><strong>\u0424\u0443\u043d\u043a\u0446\u0438\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0443 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0441 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0418\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c\u0438 API \u041e\u0421 (Windows Action Center, macOS Notification Center)<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 secure contexts (HTTPS \u0438\u043b\u0438 localhost)<\/p>\n<\/li>\n<li>\n<p>\u0422\u0440\u0435\u0431\u0443\u0435\u0442 \u044f\u0432\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f (actions) \u0432 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043e\u0432<\/p>\n<\/li>\n<\/ul>\n<p>Notifications API \u2014 \u044d\u0442\u043e \u0432\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u0435\u0431-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e. \u042d\u0442\u0438 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u044e\u0442\u0441\u044f \u0432\u043d\u0435 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u0434\u0430\u0436\u0435 \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0438\u043b\u0441\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0432\u043a\u043b\u0430\u0434\u043a\u0443 \u0438\u043b\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<h3>\u0422\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0430<\/h3>\n<p>Notifications API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 \u0442\u0435\u0441\u043d\u0443\u044e \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044e \u0441 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439 \u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u043d\u044b\u043c \u0434\u0432\u0438\u0436\u043a\u043e\u043c. \u041a\u043e\u0433\u0434\u0430 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430 \u043f\u043e\u043a\u0430\u0437 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u0431\u0440\u0430\u0443\u0437\u0435\u0440 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c API \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043a\u0430\u043d\u0430\u043b\u0430 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u041e\u0421.<\/p>\n<p>\u0421 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f, Notifications API \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043a\u0430\u0436\u0434\u043e\u0439 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b: Windows Action Center, macOS Notification Center, Linux desktop notifications \u0447\u0435\u0440\u0435\u0437 D-Bus. \u0411\u0440\u0430\u0443\u0437\u0435\u0440 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0432 \u0440\u043e\u043b\u0438 \u043c\u043e\u0441\u0442\u0430 \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u0431-\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043e\u043c \u0438 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c\u0438 API \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<p>Notifications API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u0438 \u043d\u0435\u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0435 \u2014 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439 \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u044e\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0436\u0438\u0437\u043d\u0435\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b \u0438 \u043c\u043e\u0433\u0443\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0447\u0435\u0440\u0435\u0437 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043a\u043b\u0438\u043a\u0430, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u044f \u0438\u043b\u0438 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0439.<\/p>\n<p><strong>\u0412\u0430\u0436\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/strong><\/p>\n<ul>\n<li>\n<p>Notifications API \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u044f\u0432\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0435\u0440\u0435\u0434 \u043f\u043e\u043a\u0430\u0437\u043e\u043c \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/p>\n<\/li>\n<li>\n<p>\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0442\u043e\u0437\u0432\u0430\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u043c \u0432 \u043b\u044e\u0431\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0447\u0435\u0440\u0435\u0437 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430<\/p>\n<\/li>\n<li>\n<p>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u0438\u043c\u0435\u044e\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u043f\u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0443 \u0438 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 (\u0437\u0430\u0432\u0438\u0441\u044f\u0442 \u043e\u0442 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430 \u0438 \u041e\u0421)<\/p>\n<\/li>\n<li>\n<p>Notifications API \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 secure contexts (HTTPS \u0438\u043b\u0438 localhost)<\/p>\n<\/li>\n<li>\n<p>\u0423\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430\u043c\u0438 &#171;\u041d\u0435 \u0431\u0435\u0441\u043f\u043e\u043a\u043e\u0438\u0442\u044c&#187;<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u0436\u0434\u043e\u0435 \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0435 \u0438\u043c\u0435\u0435\u0442 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID \u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0438\u043b\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u043d\u043e<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 PWA \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439<\/h3>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u043c PWA \u0447\u0442\u043e\u0431\u044b \u043d\u0430\u0448\u0438 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0432\u0435\u0437\u0434\u0435, \u0432\u043a\u043b\u044e\u0447\u0430\u044f iOS.<\/p>\n<h4>Web Application Manifest<\/h4>\n<p><strong>Web Application Manifest<\/strong> \u2014 \u044d\u0442\u043e JSON \u0444\u0430\u0439\u043b, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0434\u043b\u044f \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0430. \u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u2014 \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0439 \u0441\u0430\u0439\u0442 \u0432 Progressive Web App (PWA).<\/p>\n<h3>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 manifest.json<\/h3>\n<pre><code class=\"json\">{   \"short_name\": \"Push App\",   \"name\": \"Push Notifications App\",   \"description\": \"\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u043e\u0439 push-\u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439\",   \"icons\": [     {       \"src\": \"\/apple-touch-icon.png\",       \"sizes\": \"180x180\",       \"type\": \"image\/png\",       \"purpose\": \"maskable\"     },     {       \"src\": \"\/nextjs-192x192.png\",       \"sizes\": \"192x192\",       \"type\": \"image\/png\",       \"purpose\": \"maskable\"     },     {       \"src\": \"\/nextjs-512x512.png\",       \"sizes\": \"512x512\",       \"type\": \"image\/png\",       \"purpose\": \"maskable\"     },     {       \"src\": \"\/favicon.ico\",       \"sizes\": \"16x16 32x32\",<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-474624","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/474624","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=474624"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/474624\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=474624"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=474624"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=474624"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}