Рданной ÑÑаÑÑе ÑодеÑжиÑÑÑ Ð¸Ð½ÑоÑмаÑÐ¸Ñ Ð¾ наÑале ÑабоÑÑ Ñ ÑеÑвиÑ-воÑкеÑами: Ð±Ð°Ð·Ð¾Ð²Ð°Ñ Ð°ÑÑ Ð¸ÑекÑÑÑа, пÑоÑеÑÑÑ ÑÑÑановки и акÑиваÑии новÑÑ ÑеÑвиÑ-воÑкеÑов, обновление ÑÑÑеÑÑвÑÑÑÐ¸Ñ ÑеÑвиÑ-воÑкеÑов, ÑпÑавление кеÑем и наÑÑÑаиваемÑе оÑвеÑÑ. ÐÑÑ ÑÑо пÑиводиÑÑÑ Ð² конÑекÑÑе пÑоÑÑого пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ñ Ð¾Ñлайн-ÑÑнкÑионалÑноÑÑÑÑ.
ÐÑедпоÑÑлки поÑÐ²Ð»ÐµÐ½Ð¸Ñ Service WorkersÐдной из важнейÑÐ¸Ñ Ð¿Ñоблем, Ð¾Ñ ÐºÐ¾ÑоÑой ÑÑÑадали полÑзоваÑели веб-пÑиложений, бÑла ÑабоÑа в ÑÑловиÑÑ Ð¿Ð¾ÑеÑи ÑвÑзи. ÐÑÑÑее в миÑе веб-пÑиложение оÑÑÐ°Ð²Ð¸Ñ ÑжаÑное впеÑаÑление Ð¾Ñ Ð¸ÑполÑзованиÑ, еÑли полÑзоваÑÐµÐ»Ñ Ð½Ðµ ÑÐ¼Ð¾Ð¶ÐµÑ ÐµÐ³Ð¾ загÑÑзиÑÑ. ÐÑедпÑинималоÑÑ Ð¼Ð½Ð¾Ð³Ð¾ попÑÑок ÑÐ¾Ð·Ð´Ð°Ð½Ð¸Ñ ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ð¹, коÑоÑÑе Ð±Ñ ÑеÑили ÑÑÑ Ð¿ÑоблемÑ, и оÑÑаÑÑи ÑÑо ÑдалоÑÑ. Ðо вÑÑ Ð¶Ðµ наиважнейÑей пÑоблемой по-пÑÐµÐ¶Ð½ÐµÐ¼Ñ ÑвлÑеÑÑÑ Ð¾ÑÑÑÑÑÑвие Ñ Ð¾ÑоÑего Ð¼ÐµÑ Ð°Ð½Ð¸Ð·Ð¼Ð° Ð´Ð»Ñ ÑпÑÐ°Ð²Ð»ÐµÐ½Ð¸Ñ ÐºÐµÑем ÑеÑÑÑÑов и наÑÑÑаиваемÑми ÑеÑевÑми запÑоÑами.
ЧÑо нÑжно наÑÑÑоиÑÑ, ÑÑÐ¾Ð±Ñ Ð¿Ð¾ÑабоÑаÑÑ Ñ Service WorkerÐногие ÑÑнкÑии Service Worker ÑепеÑÑ Ð²ÐºÐ»ÑÑÐµÐ½Ñ Ð¿Ð¾ ÑмолÑÐ°Ð½Ð¸Ñ Ð² новÑÑ Ð±ÑаÑзеÑÐ°Ñ , поддеÑживаÑÑÐ¸Ñ ÑÑÑ ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ. Ðднако, еÑли Ð²Ñ Ð¾Ð±Ð½Ð°ÑÑжиÑе, ÑÑо демонÑÑÑаÑионнÑй код не ÑабоÑÐ°ÐµÑ Ð² ваÑей веÑÑии бÑаÑзеÑа, вам Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð½Ð°Ð´Ð¾Ð±Ð¸ÑÑÑÑ Ð¸Ñ Ð²ÐºÐ»ÑÑиÑÑ:
about:config
и ÑÑÑановиÑе паÑамеÑÑ dom.serviceWorkers.enabled
в знаÑение true; заÑем пеÑезапÑÑÑиÑе бÑаÑзеÑ.chrome://flags
и вклÑÑиÑе experimental-web-platform-features
; пеÑезапÑÑÑиÑе бÑаÑÐ·ÐµÑ (замеÑÑÑе, ÑÑо некоÑоÑÑе ÑÑнкÑии ÑепеÑÑ Ð²ÐºÐ»ÑÑÐµÐ½Ñ Ð¿Ð¾ ÑмолÑÐ°Ð½Ð¸Ñ Ð² бÑаÑзеÑе Chrome.)opera://flags
и вклÑÑиÑе Support for ServiceWorker
; пеÑезапÑÑÑиÑе бÑаÑзеÑ.about:flags
и поÑÑавÑÑе галоÑÐºÑ Enable service workers
; пеÑезапÑÑÑиÑе бÑаÑзеÑ.Также вам необÑ
одимо пÑедоÑÑавлÑÑÑ Ð²Ð°Ñ ÐºÐ¾Ð´ по пÑоÑÐ¾ÐºÐ¾Ð»Ñ HTTPS â Service Worker ÑÑебÑÐµÑ ÑÑого по ÑообÑажениÑм безопаÑноÑÑи. Ðо ÑÑой пÑиÑине GitHub â Ñ
оÑоÑий вÑÐ±Ð¾Ñ Ð´Ð»Ñ ÑкÑпеÑименÑов, поÑколÑÐºÑ Ð¾Ð½ поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð¿ÑоÑокол HTTPS по ÑмолÑаниÑ. ÐÐ»Ñ Ð¾Ð±Ð»ÐµÐ³ÑÐµÐ½Ð¸Ñ Ð»Ð¾ÐºÐ°Ð»Ñной ÑазÑабоÑки бÑаÑзеÑÑ ÑÑиÑаÑÑ localhost
Ñакже безопаÑнÑм origin.
ЧÑÐ¾Ð±Ñ ÑделаÑÑ Ð±Ð°Ð·Ð¾Ð²ÑÑ Ð½Ð°ÑÑÑÐ¾Ð¹ÐºÑ Service Worker, как пÑавило, нÑжно пÑойÑи ÑледÑÑÑие Ñаги:
ServiceWorkerContainer.register()
.ServiceWorkerGlobalScope
; ÑÑо, по ÑÑÑи, оÑобÑй вид конÑекÑÑа воÑкеÑа, ÑабоÑаÑÑий вне главного поÑока бÑаÑзеÑа, без доÑÑÑпа к DOM.install
вÑегда поÑÑлаеÑÑÑ Ð¿ÐµÑвÑм воÑкеÑÑ (оно Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸ÑполÑзовано Ð´Ð»Ñ Ð·Ð°Ð¿ÑÑка наÑалÑной загÑÑзки даннÑÑ
в IndexedDB, Ð´Ð»Ñ ÐºÐµÑиÑÐ¾Ð²Ð°Ð½Ð¸Ñ ÑеÑÑÑÑов). ÐаннÑй ÑÑап ÑÑодни пÑоÑедÑÑе ÑÑÑановки наÑивного или FirefoxOS-пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ â вÑе делаеÑÑÑ Ð´Ð¾ÑÑÑпнÑм Ð´Ð»Ñ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð² оÑлайн-Ñежиме.oninstall
завеÑÑÐ¸Ñ ÑÐ²Ð¾Ñ ÑабоÑÑ, ÑеÑвиÑ-воÑÐºÐµÑ ÑÑиÑаеÑÑÑ ÑÑÑановленнÑм.onactivate
, коÑоÑое обÑÑно иÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð¾ÑиÑÑки ÑеÑÑÑÑов, задейÑÑвованнÑÑ
в пÑедÑдÑÑей веÑÑии ÑкÑипÑа ÑеÑвиÑ-воÑкеÑа.register()
. То еÑÑÑ Ð´Ð¾ÐºÑÐ¼ÐµÐ½Ñ Ð¼Ð¾Ð¶ÐµÑ Ð½Ð°ÑаÑÑ Ð¶Ð¸Ð·Ð½Ñ Ñ ÑеÑвиÑ-воÑкеÑом или даже без него и пÑодолжаÑÑ Ð½Ð¾ÑмалÑно ÑабоÑаÑÑ. ÐоÑÑÐ¾Ð¼Ñ Ð´Ð¾ÐºÑменÑÑ Ð´Ð¾Ð»Ð¶Ð½Ñ Ð±ÑÑÑ Ð¿ÐµÑезагÑÑженÑ, ÑÑÐ¾Ð±Ñ Ð´ÐµÐ¹ÑÑвиÑелÑно бÑÑÑ Ð¿Ð¾Ð´ÐºÐ¾Ð½ÑÑолÑнÑми ÑеÑвиÑ-воÑкеÑÑ.СпиÑок доÑÑÑпнÑÑ ÑобÑÑий ÑеÑвиÑ-воÑкеÑов:
ÐемонÑÑÑаÑÐ¸Ñ Service WorkersЧÑÐ¾Ð±Ñ Ð¿ÑодемонÑÑÑиÑоваÑÑ ÑолÑко базовÑе моменÑÑ ÑегиÑÑÑаÑии и ÑÑÑановки ÑеÑвиÑ-воÑкеÑов, Ð¼Ñ Ñоздали пÑоÑÑое демо-пÑиложение, названое sw-test. ÐÑо пÑоÑÑÐ°Ñ Ð³Ð°Ð»ÐµÑÐµÑ Ð¸Ð·Ð¾Ð±Ñажений "Star wars Lego". Ðно иÑполÑзÑÐµÑ Ð¿ÑомиÑ-ÑÑнкÑии, ÑÑÐ¾Ð±Ñ Ð¿ÑоÑиÑаÑÑ Ð¸Ð· JSON-обÑекÑа и загÑÑзиÑÑ, иÑполÑзÑÑ ÑÐµÑ Ð½Ð¾Ð»Ð¾Ð³Ð¸Ñ Ajax, изобÑажениÑ, Ð½Ð°Ñ Ð¾Ð´ÑÑиеÑÑ Ð´Ð°Ð»ÐµÐµ нижнего кÑÐ°Ñ ÑÑÑаниÑÑ, до Ñого как они бÑдÑÑ Ð¿Ð¾ÐºÐ°Ð·Ð°Ð½Ñ. РпÑиложении Ñакже еÑÑ ÑегиÑÑÑиÑÑеÑÑÑ, ÑÑÑанавливаеÑÑÑ Ð¸ акÑивиÑÑеÑÑÑ ÑеÑвиÑ-воÑкеÑ, и, в ÑлÑÑае еÑли бÑаÑÐ·ÐµÑ Ð¿Ð¾Ð´Ð´ÐµÑÐ¶Ð¸Ð²Ð°ÐµÑ ÑпеÑиÑикаÑÐ¸Ñ Service Worker, запÑаÑиваемÑе ÑеÑÑÑÑÑ Ð±ÑдÑÑ Ð·Ð°ÐºÐµÑиÑованÑ, и пÑиложение бÑÐ´ÐµÑ ÑабоÑаÑÑ Ð² оÑлайн-Ñежиме!
ÐÑ Ð¼Ð¾Ð¶ÐµÑе поÑмоÑÑеÑÑ Ð¸ÑÑ Ð¾Ð´Ð½Ñй код на GitHub, а Ñакже ÑÑÐ¾Ñ Ð¶Ð¸Ð²Ð¾Ð¹ пÑимеÑ. ÐдинÑÑвенное, ÑÑо Ð¼Ñ ÑÑÑ ÑаÑÑмоÑÑим, ÑÑо пÑÐ¾Ð¼Ð¸Ñ (ÑмоÑÑиÑе app.js ÑÑÑоки 22-47), модиÑиÑиÑÐ¾Ð²Ð°Ð½Ð½Ð°Ñ Ð²ÐµÑÑÐ¸Ñ Ñого, о коÑоÑом Ð²Ñ ÑиÑали вÑÑе в Ñазделе ТеÑÑÐ¾Ð²Ð°Ñ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑаÑÐ¸Ñ Ð¿ÑомиÑов. РазниÑа в ÑледÑÑÑем:
for()
, ÑÑо Ð±Ñ Ð½Ðµ ÑÑабоÑало, Ñак как ÑÑÐ¾Ñ Ð¿ÑÐ¾Ð¼Ð¸Ñ Ð½Ðµ бÑл Ð±Ñ Ð²Ñполнен во вÑÐµÐ¼Ñ ÑекÑÑей иÑеÑаÑии Ñикла (ÑÑо ÑинÑ
ÑоннÑй пÑоÑеÑÑ).ÐÑак, пеÑÐµÑ Ð¾Ð´Ð¸Ð¼ к Service Worker!
РегиÑÑÑаÑÐ¸Ñ Ð²Ð¾ÑкеÑовÐиже пÑедÑÑавлен пеÑвÑй блок кода Ñайла app.js. ÐÑо ÑоÑка Ð²Ñ Ð¾Ð´Ð° в Service Worker.
if ("serviceWorker" in navigator) {
navigator.serviceWorker
.register("./sw-test/sw.js", { scope: "./sw-test/" })
.then((reg) => {
// ÑегиÑÑÑаÑÐ¸Ñ ÑÑабоÑала
console.log("Registration succeeded. Scope is " + reg.scope);
})
.catch((error) => {
// ÑегиÑÑÑаÑÐ¸Ñ Ð¿ÑоÑла неÑдаÑно
console.log("Registration failed with " + error);
});
}
ServiceWorkerContainer.register()
. СеÑвиÑ-воÑÐºÐµÑ Ð¿ÑедÑÑавлÑÐµÑ Ñобой JavaScript-Ñайл пÑÐ¸Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ (обÑаÑиÑе внимание, ÑÑо URL ÑказÑваеÑÑÑ Ð¾ÑноÑиÑелÑно "коÑнÑ", а не меÑÑа ÑаÑÐ¿Ð¾Ð»Ð¾Ð¶ÐµÐ½Ð¸Ñ JS-Ñайла, ÑегиÑÑÑиÑÑÑÑего ÑеÑвиÑ-воÑкеÑ).'./sw-test/'
. ÐÑли Ð²Ñ Ð½Ðµ ÑкажеÑе его, Ñо бÑÐ´ÐµÑ Ð¸ÑполÑзовано знаÑение по ÑмолÑаниÑ; Ð¼Ñ Ð¶Ðµ Ñказали его ÑолÑко в ÑелÑÑ
иллÑÑÑÑаÑии..then()
бÑл иÑполÑзован Ð´Ð»Ñ Ð¾Ð±ÑабоÑки ÑÑпеÑной ÑегиÑÑÑаÑии. ÐÑли пÑÐ¾Ð¼Ð¸Ñ ÑазÑеÑиÑÑÑ ÑÑпеÑно, Ñо код, пеÑеданнÑй ÑÑÐ¾Ð¼Ñ Ð¼ÐµÑодÑ, бÑÐ´ÐµÑ Ð²Ñполнен..catch()
, коÑоÑÐ°Ñ Ð±ÑÐ´ÐµÑ Ð²Ñполнена в ÑлÑÑае, еÑли пÑÐ¾Ð¼Ð¸Ñ Ð±ÑÐ´ÐµÑ Ð¾ÑклонÑн.ÐÑедÑдÑÑий код ÑегиÑÑÑиÑÑÐµÑ ÑеÑвиÑ-воÑкеÑа, коÑоÑÑй ÑабоÑÐ°ÐµÑ Ð² worker-конÑекÑÑе, и ÑледоваÑелÑно, не Ð¸Ð¼ÐµÐµÑ Ð´Ð¾ÑÑÑпа к DOM. ÐаÑем Ð²Ñ Ð·Ð°Ð¿ÑÑкаеÑе код в ÑеÑвиÑ-воÑкеÑе, вне ваÑÐ¸Ñ ÑÑÑаниÑ, ÑÑÐ¾Ð±Ñ ÐºÐ¾Ð½ÑÑолиÑоваÑÑ Ð¸Ñ Ð·Ð°Ð³ÑÑзкÑ.
Ðдин ÑеÑвиÑ-воÑÐºÐµÑ Ð¼Ð¾Ð¶ÐµÑ ÐºÐ¾Ð½ÑÑолиÑоваÑÑ Ð½ÐµÑколÑко ÑÑÑаниÑ. ÐаждÑй Ñаз, когда загÑÑжаеÑÑÑ ÑÑÑаниÑа, Ð½Ð°Ñ Ð¾Ð´ÑÑаÑÑÑ Ð² пÑÐµÐ´ÐµÐ»Ð°Ñ Ð¾Ð±Ð»Ð°ÑÑи видимоÑÑи, ÑеÑвиÑ-воÑÐºÐµÑ Ð±ÑÐ´ÐµÑ ÑÑÑановлен на ней и наÑнÑÑ ÑабоÑÑ. ÐоÑÑÐ¾Ð¼Ñ Ð±ÑдÑÑе оÑÑоÑÐ¾Ð¶Ð½Ñ Ñ Ð¿Ñименением глобалÑнÑÑ Ð¿ÐµÑеменнÑÑ Ð² ÑкÑипÑÐ°Ñ ÑеÑвиÑ-воÑкеÑов, поÑÐ¾Ð¼Ñ ÐºÐ°Ðº Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑаниÑÑ Ð½ÐµÑ Ñвоего ÑникалÑного ÑкземплÑÑа ÑеÑвиÑ-воÑкеÑа.
ÐоÑÐµÐ¼Ñ Ð¼Ð¾Ð¹ ÑеÑвиÑ-воÑÐºÐµÑ Ð½Ðµ пÑоÑÑл ÑегиÑÑÑаÑиÑ?ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑоизойÑи по ÑледÑÑÑим пÑиÑинам:
https://mdn.github.io/sw-test/sw.js
, коÑÐ½ÐµÐ²Ð°Ñ Ð¿Ð°Ð¿ÐºÐ° â https://mdn.github.io/sw-test/
. Ðо в каÑеÑÑве пÑÑи к ÑеÑвиÑ-воÑкеÑÑ Ð½Ñжно ÑказÑваÑÑ /sw-test/sw.js
, а не /sw.js
.Также обÑаÑиÑе внимание:
Service-Worker-Allowed
, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑказаÑÑ ÑпиÑок макÑималÑнÑÑ
облаÑÑей видимоÑÑи Ð´Ð»Ñ ÑÑиÑ
воÑкеÑов.ÐоÑле Ñого как Ð²Ð°Ñ ÑеÑвиÑ-воÑÐºÐµÑ Ð±ÑÐ´ÐµÑ Ð·Ð°ÑегиÑÑÑиÑован, бÑаÑÐ·ÐµÑ Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð¿ÑобоваÑÑ ÑÑÑановиÑÑ ÐµÐ³Ð¾ и акÑивиÑоваÑÑ Ð½Ð° ÑÑÑаниÑе/ÑайÑе.
СобÑÑие install Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÐµÑ Ð¿Ð¾Ñле Ñого как ÑÑÑановка ÑÑпеÑно завеÑÑиÑÑÑ. ÐÑо ÑобÑÑие иÑполÑзÑеÑÑÑ Ð³Ð»Ð°Ð²Ð½Ñм обÑазом Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½Ð¸ÑÑ ÐºÐµÑ Ð±ÑаÑзеÑа ÑеÑÑÑÑами, необÑ
одимÑми Ð´Ð»Ñ ÑÑпеÑного запÑÑка в оÑлайн-Ñежиме. ÐÐ»Ñ ÑÑого иÑполÑзÑеÑÑÑ Ð½Ð¾Ð²Ñй API Ñ
ÑанилиÑа Service Worker â cache
â глобалÑнÑй Ð´Ð»Ñ Ð²ÑеÑ
ÑеÑвиÑ-воÑкеÑов, коÑоÑÑй позволÑÐµÑ Ð½Ð°Ð¼ Ñ
ÑаниÑÑ ÑезÑлÑÑаÑÑ Ð·Ð°Ð¿ÑоÑов, иÑполÑзÑÑ Ð² каÑеÑÑве клÑÑа Ð´Ð»Ñ Ð¸Ñ
полÑÑÐµÐ½Ð¸Ñ Ñами запÑоÑÑ. ÐÑÐ¾Ñ API ÑабоÑÐ°ÐµÑ Ð°Ð½Ð°Ð»Ð¾Ð³Ð¸Ñно ÑÑандаÑÑÐ½Ð¾Ð¼Ñ ÐºÐµÑÑ Ð±ÑаÑзеÑа, но ÑолÑко Ð´Ð»Ñ Ð²Ð°Ñего домена. ÐаннÑе в кеÑе ÑоÑ
ÑанÑÑÑÑÑ Ð´Ð¾ ÑеÑ
поÑ, пока Ð²Ñ Ñами не ÑеÑиÑе иÑ
ÑдалиÑÑ â Ð²Ñ Ð¸Ð¼ÐµÐµÑе полнÑй конÑÑолÑ.
ÐавайÑе наÑнÑм ÑÑÐ¾Ñ Ñаздел поÑмоÑÑев на ÑÑÐ°Ð³Ð¼ÐµÐ½Ñ ÐºÐ¾Ð´Ð° ниже â ÑÑо пеÑвÑй блок кода, коÑоÑÑй Ð²Ñ ÑвидиÑе в наÑем ÑеÑвиÑ-воÑкеÑе:
self.addEventListener("install", (event) => {
event.waitUntil(
caches.open("v1").then((cache) => {
return cache.addAll([
"./sw-test/",
"./sw-test/index.html",
"./sw-test/style.css",
"./sw-test/app.js",
"./sw-test/image-list.js",
"./sw-test/star-wars-logo.jpg",
"./sw-test/gallery/",
"./sw-test/gallery/bountyHunters.jpg",
"./sw-test/gallery/myLittleVader.jpg",
"./sw-test/gallery/snowTroopers.jpg",
]);
}),
);
});
install
к ÑеÑвиÑ-воÑкеÑÑ (оÑнÑне self
), и заÑем вÑзÑваем меÑод ExtendableEvent.waitUntil()
обÑекÑа ÑобÑÑиÑ. Ð¢Ð°ÐºÐ°Ñ ÐºÐ¾Ð½ÑÑÑÑкÑÐ¸Ñ Ð³Ð°ÑанÑиÑÑеÑ, ÑÑо ÑеÑвиÑ-воÑÐºÐµÑ Ð½Ðµ бÑÐ´ÐµÑ ÑÑÑановлен, пока код, пеÑеданнÑй внÑÑÑи waitUntil()
, не завеÑÑиÑÑÑ Ñ ÑÑпеÑ
ом.waitUntil()
Ð¼Ñ Ð¸ÑполÑзÑем меÑод caches.open(), ÑÑÐ¾Ð±Ñ ÑоздаÑÑ Ð½Ð¾Ð²Ñй кеÑ, коÑоÑÑй назовÑм v1
, ÑÑо бÑÐ´ÐµÑ Ð¿ÐµÑÐ²Ð°Ñ Ð²ÐµÑÑÐ¸Ñ ÐºÐµÑа ÑеÑÑÑÑов. ÐÑÐ¾Ñ Ð¼ÐµÑод возвÑаÑÐ°ÐµÑ Ð¿ÑÐ¾Ð¼Ð¸Ñ Ð´Ð»Ñ Ñозданного кеÑа; когда он вÑполниÑÑÑ, Ñ Ð¾Ð±ÑекÑа Ñозданного кеÑа Ð¼Ñ Ð²Ñзовем меÑод addAll()
, коÑоÑÑй в каÑеÑÑве паÑамеÑÑа Ð¾Ð¶Ð¸Ð´Ð°ÐµÑ Ð¿Ð¾Ð»ÑÑиÑÑ Ð¼Ð°ÑÑив origin-оÑноÑиÑелÑнÑÑ
URL вÑеÑ
ÑеÑÑÑÑов, коÑоÑÑе Ð¼Ñ Ñ
оÑим Ñ
ÑаниÑÑ Ð² кеÑе.ТепеÑÑ ÑеÑÑÑÑÑ Ð²Ð°Ñего ÑайÑа наÑ
одÑÑÑÑ Ð² кеÑе и вам необÑ
одимо ÑказаÑÑ ÑеÑвиÑ-воÑкеÑÑ, ÑÑо делаÑÑ Ñ ÑÑим конÑенÑом. ÐÑо легко ÑделаÑÑ, обÑабоÑав ÑобÑÑие fetch
.
СобÑÑие fetch
Ð²Ð¾Ð·Ð½Ð¸ÐºÐ°ÐµÑ ÐºÐ°Ð¶Ð´Ñй Ñаз, когда запÑаÑиваÑÑÑÑ Ð»ÑбÑе подконÑÑолÑнÑе ÑеÑвиÑ-воÑкеÑÑ ÑеÑÑÑÑÑ, к коÑоÑÑм оÑноÑÑÑÑÑ Ð´Ð¾ÐºÑменÑÑ Ð¸Ð· облаÑÑи видимоÑÑи и дÑÑгие ÑеÑÑÑÑÑ, ÑвÑзаннÑе Ñ ÑÑими докÑменÑами (напÑимеÑ, еÑли в index.html пÑоиÑÑ
Ð¾Ð´Ð¸Ñ ÐºÑоÑÑ-доменнÑй запÑÐ¾Ñ Ð´Ð»Ñ Ð·Ð°Ð³ÑÑзки изобÑажениÑ, Ñо он Ñоже попадÑÑ Ð² ÑеÑвиÑ-воÑкеÑ).
ÐÑ Ð¼Ð¾Ð¶ÐµÑе подклÑÑиÑÑ Ðº ÑеÑвиÑ-воÑкеÑÑ Ð¾Ð±ÑабоÑÑик ÑобÑÑÐ¸Ñ fetch
и внÑÑÑи него на обÑекÑе ÑобÑÑÐ¸Ñ Ð²ÑзваÑÑ Ð¼ÐµÑод respondWith()
, ÑÑÐ¾Ð±Ñ Ð·Ð°Ð¼ÐµÐ½Ð¸ÑÑ Ð¾ÑвеÑÑ Ð¸ показаÑÑ ÑобÑÑвеннÑÑ "магиÑ".
self.addEventListener("fetch", (event) => {
event
.respondWith
// Ð¼Ð°Ð³Ð¸Ñ Ð¿ÑоиÑÑ
Ð¾Ð´Ð¸Ñ Ð·Ð´ÐµÑÑ
();
});
ÐÐ»Ñ Ð½Ð°Ñала, на каждÑй ÑеÑевой запÑÐ¾Ñ Ð¼Ñ Ð¼Ð¾Ð¶ÐµÐ¼ оÑдаÑÑ Ð² оÑÐ²ÐµÑ ÑеÑÑÑÑ, Ñей url ÑооÑвеÑÑÑвÑÐµÑ Ð·Ð°Ð¿ÑоÑÑ:
self.addEventListener("fetch", (event) => {
event.respondWith(caches.match(event.request));
});
caches.match(event.request)
позволÑÐµÑ Ð½Ð°Ð¼ пÑовеÑÑÑÑ ÑеÑевой запÑÐ¾Ñ ÑеÑÑÑÑа на ÑооÑвеÑÑÑвие какомÑ-либо доÑÑÑÐ¿Ð½Ð¾Ð¼Ñ Ð² кеÑе ÑеÑÑÑÑÑ, еÑли Ñакой ÑеÑÑÑÑ Ð¸Ð¼ÐµÐµÑÑÑ. СооÑвеÑÑÑвие пÑовеÑÑеÑÑÑ Ð¿Ð¾ url и изменÑемÑм заголовкам.
ÐавайÑе ÑаÑÑмоÑÑим неÑколÑко дÑÑгиÑ
ваÑианÑов ÑеализаÑии наÑей магии (ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð±Ð¾Ð»ÑÑе инÑоÑмаÑии об инÑеÑÑейÑаÑ
Request
и Response
ÑмоÑÑиÑе докÑменÑаÑÐ¸Ñ Ðº Fetch API.)
ÐонÑÑÑÑкÑоÑ
позволÑÐµÑ Ð²Ð°Ð¼ ÑоздаваÑÑ ÑобÑÑвеннÑе оÑвеÑÑ. Рданном ÑлÑÑае, Ð¼Ñ Ð²Ñего лиÑÑ Ð²Ð¾Ð·Ð²ÑаÑаем пÑоÑÑÑÑ ÑекÑÑовÑÑ ÑÑÑокÑ:Response()
new Response("Hello from your friendly neighbourhood service worker!");
Ð ÑÑом более Ñложном обÑекÑе Response показано, как Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе пеÑедаÑÑ Ð½Ð°Ð±Ð¾Ñ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¾Ð² в Ñвой оÑвеÑ, ÑмÑлиÑÑÑ ÑÑандаÑÑнÑй HTTP-оÑвеÑ. ÐдеÑÑ Ð¼Ñ Ð¿ÑоÑÑо ÑообÑаем бÑаÑзеÑÑ, Ñем ÑвлÑеÑÑÑ ÑодеÑжимое оÑвеÑа:
new Response(
"<p>Hello from your friendly neighbourhood service worker!</p>",
{
headers: { "Content-Type": "text/html" },
},
);
ÐÑли Ñовпадение не бÑло найдено в кеÑе, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе попÑоÑиÑÑ Ð±ÑаÑÐ·ÐµÑ Ð·Ð°Ð³ÑÑзиÑÑ
ÑÐ¾Ñ Ð¶Ðµ ÑеÑÑÑÑ, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð½Ð¾Ð²Ñй Ñайл ÑеÑез обÑÑнÑÑ ÑеÑÑ, еÑли она доÑÑÑпна:
ÐÑли инÑоÑмаÑиÑ, ÑооÑвеÑÑÑвÑÑÑÐ°Ñ Ð·Ð°Ð¿ÑоÑÑ, в кеÑе не найдена, а Ñакже ÑеÑÑ Ð½Ðµ доÑÑÑпна, Ñо Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе пÑоÑÑо оÑвеÑиÑÑ Ð½Ð° запÑÐ¾Ñ ÐºÐ°ÐºÐ¾Ð¹-либо ÑÑÑаниÑей по ÑмолÑаниÑ, коÑоÑÐ°Ñ Ñ
ÑаниÑÑÑ Ð² кеÑе, иÑполÑзÑÑ match()
:
caches.match("./fallback.html");
ÐÑ Ð¼Ð¾Ð¶ÐµÑе полÑÑиÑÑ Ð±Ð¾Ð»ÑÑе инÑоÑмаÑии о каждом запÑоÑе, иÑполÑзÑÑ Ð´Ð»Ñ ÑÑого ÑвойÑÑва обÑекÑа Request
, коÑоÑÑй можно полÑÑиÑÑ ÐºÐ°Ðº ÑвойÑÑво обÑекÑа FetchEvent
:
event.request.url;
event.request.method;
event.request.headers;
event.request.body;
ÐÑак, caches.match(event.request)
оÑÑабоÑÐ°ÐµÑ ÐºÐ°Ðº нÑжно ÑолÑко в Ñом ÑлÑÑае, еÑли в кеÑе ÑеÑвиÑ-воÑкеÑа бÑÐ´ÐµÑ Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾ ÑооÑвеÑÑÑвие запÑоÑÑ. Ðо ÑÑо пÑоизойдÑÑ, еÑли Ñакого ÑооÑвеÑÑÑÐ²Ð¸Ñ Ð½Ðµ бÑÐ´ÐµÑ Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾? ÐÑли Ð¼Ñ Ð½Ðµ пÑедоÑÑавим никакого меÑ
анизма обÑабоÑки Ñакой ÑиÑÑаÑии, Ñо пÑÐ¾Ð¼Ð¸Ñ Ð²ÑполниÑÑÑ Ñо знаÑением undefined
и Ð¼Ñ Ð½Ðµ полÑÑим никакого знаÑениÑ.
Ð ÑÑаÑÑÑÑ, ÑеÑвиÑ-воÑкеÑÑ Ð¸Ð¼ÐµÑÑ ÑÑÑÑкÑÑÑÑ Ð¾ÑнованнÑÑ Ð½Ð° пÑомиÑÐ°Ñ , ÑÑо Ð´ÐµÐ»Ð°ÐµÑ ÑÑивиалÑной ÑакÑÑ Ð¾Ð±ÑабоÑÐºÑ Ð¸ пÑедоÑÑавлÑÐµÑ Ð±Ð¾Ð»ÑÑое колиÑеÑÑво ÑпоÑобов ÑÑпеÑно обÑабоÑаÑÑ Ð·Ð°Ð¿ÑоÑ:
self.addEventListener("fetch", (event) => {
event.respondWith(
caches.match(event.request).then((response) => {
return response || fetch(event.request);
}),
);
});
ÐÑли пÑÐ¾Ð¼Ð¸Ñ Ð±ÑÐ´ÐµÑ Ð¾ÑклонÑн, ÑÑнкÑÐ¸Ñ catch()
веÑнÑÑ Ð¾Ð±ÑÑнÑй ÑеÑевой запÑÐ¾Ñ Ðº внеÑÐ½ÐµÐ¼Ñ ÑеÑÑÑÑÑ. ÐÑо знаÑиÑ, ÑÑо, еÑли ÑеÑÑ Ð´Ð¾ÑÑÑпна, Ñо ÑеÑÑÑÑ Ð¿ÑоÑÑо загÑÑзиÑÑÑ Ñ ÑеÑвеÑа.
ÐÑли же Ð¼Ñ Ð±Ñли доÑÑаÑоÑно ÑмнÑ, Ñо Ð¼Ñ Ð½Ðµ ÑÑали Ð±Ñ Ð¿ÑоÑÑо возвÑаÑаÑÑ ÑеÑевой запÑоÑ, а ÑÐ¾Ñ Ñанили Ð±Ñ ÐµÐ³Ð¾ ÑезÑлÑÑÐ°Ñ Ð² кеÑе, ÑÑÐ¾Ð±Ñ Ð¸Ð¼ÐµÑÑ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾ÑÑÑ Ð¿Ð¾Ð»ÑÑиÑÑ ÐµÐ³Ð¾ в оÑлайн-Ñежиме. Ð ÑлÑÑае Ñ Ð½Ð°Ñим демо-пÑиложением "Star Wars gallery", ÑÑо ознаÑаеÑ, ÑÑо, еÑли в галеÑÐµÑ Ð±ÑÐ´ÐµÑ Ð´Ð¾Ð±Ð°Ð²Ð»ÐµÐ½Ð¾ еÑÑ Ð¾Ð´Ð½Ð¾ изобÑажение, Ñо оно бÑÐ´ÐµÑ Ð¿Ð¾Ð»ÑÑено и ÑÐ¾Ñ Ñанено в кеÑе:
self.addEventListener("fetch", (event) => {
event.respondWith(
caches.match(event.request).then((resp) => {
return (
resp ||
fetch(event.request).then((response) => {
return caches.open("v1").then((cache) => {
cache.put(event.request, response.clone());
return response;
});
})
);
}),
);
});
ÐдеÑÑ Ð¼Ñ Ð²Ð¾Ð·Ð²ÑаÑаем обÑÑнÑй ÑеÑевой запÑоÑ, коÑоÑÑй возвÑаÑÑн вÑзовом fetch(event.request);
ÑÑÐ¾Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ñакже ÑвлÑеÑÑÑ Ð¿ÑомиÑом. Ðогда пÑÐ¾Ð¼Ð¸Ñ ÑазÑеÑиÑÑÑ, Ð¼Ñ Ð¿Ð¾Ð»ÑÑим ÐºÐµÑ Ð²Ñзвав caches.open('v1');
ÑÑÐ¾Ñ Ð¼ÐµÑод Ñакже возвÑаÑÐ°ÐµÑ Ð¿ÑомиÑ. Ðогда ÑазÑеÑиÑÑÑ Ñже вÑоÑой пÑомиÑ, бÑÐ´ÐµÑ Ð¸ÑполÑзован вÑзов cache.put()
, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð¼ÐµÑÑиÑÑ ÑеÑÑÑÑ Ð² кеÑ. РеÑÑÑÑ Ð¿Ð¾Ð»ÑÑен ÑеÑез event.request
, а оÑÐ²ÐµÑ â ÑеÑез клониÑование response.clone()
. Ðлон помеÑаеÑÑÑ Ð² кеÑ, а оÑигиналÑнÑй оÑÐ²ÐµÑ Ð¿ÐµÑедаÑÑÑÑ Ð±ÑаÑзеÑÑ, коÑоÑÑй пеÑедаÑÑ ÐµÐ³Ð¾ ÑÑÑаниÑе, коÑоÑÐ°Ñ Ð·Ð°Ð¿ÑоÑила ÑеÑÑÑÑ.
ÐоÑемÑ? ÐоÑÐ¾Ð¼Ñ ÑÑо поÑоки запÑоÑа и оÑвеÑа могÑÑ Ð±ÑÑÑ Ð¿ÑоÑиÑÐ°Ð½Ñ ÑолÑко единождÑ. ЧÑÐ¾Ð±Ñ Ð¾ÑÐ²ÐµÑ Ð±Ñл полÑÑен бÑаÑзеÑом и ÑÐ¾Ñ ÑанÑн в кеÑе, нам нÑжно клониÑоваÑÑ ÐµÐ³Ð¾. Так оÑигиналÑнÑй обÑÐµÐºÑ Ð¾ÑпÑавиÑÑÑ Ð±ÑаÑзеÑÑ, а клон бÑÐ´ÐµÑ Ð·Ð°ÐºÐµÑиÑован. Ðба они бÑдÑÑ Ð¿ÑоÑиÑÐ°Ð½Ñ ÐµÐ´Ð¸Ð½Ð¾Ð¶Ð´Ñ.
У Ð½Ð°Ñ Ð²Ñе еÑÑ Ð¾ÑÑаÑÑÑÑ ÐµÐ´Ð¸Ð½ÑÑÐ²ÐµÐ½Ð½Ð°Ñ Ð¿Ñоблема - еÑли на какой-либо запÑÐ¾Ñ Ð² кеÑе не бÑÐ´ÐµÑ Ð½Ð°Ð¹Ð´ÐµÐ½Ð¾ ÑооÑвеÑÑÑвие, и в ÑÑÐ¾Ñ Ð¼Ð¾Ð¼ÐµÐ½Ñ ÑеÑÑ Ð½Ðµ доÑÑÑпна, Ñо Ð½Ð°Ñ Ð·Ð°Ð¿ÑÐ¾Ñ Ð·Ð°Ð²ÐµÑÑиÑÑÑ Ð½ÐµÑдаÑно. ÐавайÑе ÑеализÑем запаÑной ваÑÐ¸Ð°Ð½Ñ Ð¿Ð¾ ÑмолÑаниÑ, пÑи коÑоÑом полÑзоваÑелÑ, в опиÑанном ÑлÑÑае, бÑÐ´ÐµÑ Ð¿Ð¾Ð»ÑÑаÑÑ Ñ Ð¾ÑÑ ÑÑо-нибÑдÑ:
self.addEventListener("fetch", (event) => {
event.respondWith(
caches
.match(event.request)
.then((resp) => {
return (
resp ||
fetch(event.request).then((response) => {
let responseClone = response.clone();
caches.open("v1").then((cache) => {
cache.put(event.request, responseClone);
});
return response;
})
);
})
.catch(() => {
return caches.match("./sw-test/gallery/myLittleVader.jpg");
}),
);
});
ÐдеÑÑ Ð¼Ñ ÑеÑили обÑабаÑÑваÑÑ ÑолÑко каÑÑинки, поÑÐ¾Ð¼Ñ ÑÑо единÑÑвеннÑе запÑоÑÑ, коÑоÑÑе могÑÑ Ð½Ðµ ÑдаÑÑÑÑ â ÑÑо загÑÑзка новÑÑ
каÑÑинок, Ñак как вÑе оÑÑалÑное бÑло закеÑиÑовано во вÑÐµÐ¼Ñ Ð¾Ð±ÑабоÑки ÑобÑÑÐ¸Ñ install
, коÑоÑое Ð¼Ñ Ð¾Ð±ÑÑждали Ñанее.
ÐÑли поÑле Ñого, как ÑеÑвиÑ-воÑÐºÐµÑ Ð±Ñл ÑÑÑановлен, ÑÑала доÑÑÑпна его Ð½Ð¾Ð²Ð°Ñ Ð²ÐµÑÑиÑ, Ñо пÑи обновлении или загÑÑзке ÑÑÑаниÑÑ Ð¾Ð½Ð° бÑÐ´ÐµÑ ÑÑÑановлена в Ñоновом Ñежиме, но не бÑÐ´ÐµÑ Ð°ÐºÑивиÑована. Ðна бÑÐ´ÐµÑ Ð°ÐºÑивиÑована, лиÑÑ ÐºÐ¾Ð³Ð´Ð° не оÑÑанеÑÑÑ Ð½Ð¸ одной ÑÑÑаниÑÑ, иÑполÑзÑÑÑей ÑÑаÑÑÑ Ð²ÐµÑÑÐ¸Ñ ÑеÑвиÑ-воÑкеÑа. Ðак ÑолÑко Ñакие ÑÑÑаниÑÑ Ð¿ÐµÑеÑÑанÑÑ Ð·Ð°Ð³ÑÑжаÑÑÑÑ, акÑивиÑÑеÑÑÑ Ð½Ð¾Ð²Ñй ÑеÑвиÑ-воÑкеÑ.
ÐÑимеÑание: ÐÑо можно обойÑи Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ Clients.claim()
.
ÐбновиÑÑ Ð¾Ð±ÑабоÑÑик ÑобÑÑÐ¸Ñ install
в новой веÑÑии ÑеÑвиÑ-воÑкеÑа можно Ñаким ÑпоÑобом (обÑаÑиÑе внимание на Ð½Ð¾Ð¼ÐµÑ Ð½Ð¾Ð²Ð¾Ð¹ веÑÑии):
const addResourcesToCache = async (resources) => {
const cache = await caches.open("v2");
await cache.addAll(resources);
};
self.addEventListener("install", (event) => {
event.waitUntil(
addResourcesToCache([
"/",
"/index.html",
"/style.css",
"/app.js",
"/image-list.js",
// ...
// подклÑÑение пÑоÑиÑ
ÑеÑÑÑÑов Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ð¹ веÑÑии...
]),
);
});
Ðо вÑÐµÐ¼Ñ ÑÑÑановки ÑеÑвиÑ-воÑкеÑа пÑедÑдÑÑÐ°Ñ Ð²ÐµÑÑÐ¸Ñ Ð¾ÑвеÑÐ°ÐµÑ Ð·Ð° обÑабоÑÐºÑ Ð·Ð°Ð¿ÑоÑов. ÐÐ¾Ð²Ð°Ñ Ð²ÐµÑÑÐ¸Ñ ÑÑÑанавливаеÑÑÑ Ð² Ñоновом Ñежиме. ÐоÑколÑÐºÑ Ð²ÑзÑваеÑÑÑ Ð½Ð¾Ð²Ñй ÐºÐµÑ v2
, пÑедÑдÑÑий ÐºÐµÑ v1
не заÑÑагиваеÑÑÑ.
Ðогда Ñже ни одна ÑÑÑаниÑа не иÑполÑзÑÐµÑ Ð¿ÑедÑдÑÑÑÑ Ð²ÐµÑÑиÑ, новÑй воÑÐºÐµÑ Ð°ÐºÑивиÑÑеÑÑÑ Ð¸ ÑÑановиÑÑÑ Ð¾ÑвеÑÑÑвеннÑм за обÑабоÑÐºÑ Ð·Ð°Ð¿ÑоÑов.
Удаление ÑÑаÑого кеÑаÐак можно ÑвидеÑÑ Ð² пÑедÑдÑÑем пÑимеÑе, пÑи обновлении ÑеÑвиÑ-воÑкеÑа до новой веÑÑии, ÑоздаÑÑÑÑ Ð½Ð¾Ð²Ñй ÐºÐµÑ Ð² обÑабоÑÑике ÑобÑÑий install
. Ðока еÑÑÑ Ð¾ÑкÑÑÑÑе ÑÑÑаниÑÑ, коÑоÑÑе конÑÑолиÑÑÑÑÑÑ Ð¿ÑедÑдÑÑей веÑÑией воÑкеÑа, необÑ
одимо ÑоÑ
ÑанÑÑÑ Ð¾Ð±Ð° кеÑа, Ñак как пÑедÑдÑÑей веÑÑии ÑÑебÑеÑÑÑ ÑÐ²Ð¾Ñ Ð²ÐµÑÑÐ¸Ñ ÐºÐµÑа. Ðожно иÑполÑзоваÑÑ ÑобÑÑие activate
Ð´Ð»Ñ ÑÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð´Ð°Ð½Ð½ÑÑ
из пÑедÑдÑÑиÑ
кеÑей.
ÐÑомиÑÑ, пеÑеданнÑе в waitUntil()
, бÑдÑÑ Ð±Ð»Ð¾ÐºÐ¸ÑоваÑÑ Ð´ÑÑгие ÑобÑÑÐ¸Ñ Ð´Ð¾ завеÑÑениÑ, поÑÑÐ¾Ð¼Ñ Ð¼Ð¾Ð¶Ð½Ð¾ бÑÑÑ ÑвеÑеннÑм, ÑÑо опеÑаÑÐ¸Ñ Ð¾ÑиÑÑки бÑÐ´ÐµÑ Ð·Ð°Ð²ÐµÑÑена к ÑÐ¾Ð¼Ñ Ð²Ñемени, когда бÑÐ´ÐµÑ Ð¿Ð¾Ð»ÑÑено пеÑвое ÑобÑÑие fetch
Ð´Ð»Ñ Ð½Ð¾Ð²Ð¾Ð³Ð¾ ÑеÑвиÑ-воÑкеÑа.
const deleteCache = async (key) => {
await caches.delete(key);
};
const deleteOldCaches = async () => {
const cacheKeepList = ["v2"];
const keyList = await caches.keys();
const cachesToDelete = keyList.filter((key) => !cacheKeepList.includes(key));
await Promise.all(cachesToDelete.map(deleteCache));
};
self.addEventListener("activate", (event) => {
event.waitUntil(deleteOldCaches());
});
ÐнÑÑÑÑменÑÑ ÑазÑабоÑÑика
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4