یکی از جنبه های کلیدی برنامه های وب پیشرو این است که قابل اعتماد هستند. آنها می توانند دارایی ها را به سرعت بارگیری کنند، کاربران را درگیر نگه می دارند و بلافاصله بازخورد ارائه می دهند، حتی در شرایط بد شبکه. چگونه ممکن است؟ با تشکر از رویداد fetch
کارگر خدمات.
رویداد واکشی
رویداد fetch
به ما امکان میدهد هر درخواست شبکهای را که توسط PWA در محدوده سرویسدهنده ارائه میشود، هم برای درخواستهای یکسان و هم برای درخواستهای متقاطع، رهگیری کنیم. علاوه بر درخواستهای ناوبری و دارایی، واکشی از یک سرویسکار نصبشده اجازه میدهد بازدید از صفحه پس از اولین بارگذاری سایت بدون تماس شبکه ارائه شود.
کنترلکننده fetch
همه درخواستهای یک برنامه، از جمله نشانیهای اینترنتی و سرصفحههای HTTP را دریافت میکند و به توسعهدهنده برنامه اجازه میدهد تصمیم بگیرد که چگونه آنها را پردازش کند.
کارمند خدمات شما می تواند درخواستی را به شبکه ارسال کند، با پاسخی که قبلاً در حافظه پنهان شده است پاسخ دهد یا پاسخ جدیدی ایجاد کند. انتخاب با شماست. در اینجا یک مثال ساده آورده شده است:
self.addEventListener("fetch", event => {
console.log(`URL requested: ${event.request.url}`);
});
پاسخ به یک درخواست
وقتی درخواستی به کارمند خدمات شما می رسد، دو کار وجود دارد که می توانید انجام دهید. می توانید آن را نادیده بگیرید، که به آن اجازه می دهد به شبکه برود، یا می توانید به آن پاسخ دهید. پاسخ به درخواستهای داخل سرویسکار به این معناست که چگونه میتوانید انتخاب کنید چه چیزی و چگونه به PWA خود بازگردانده شود، حتی زمانی که کاربر آفلاین است.
برای پاسخ به یک درخواست ورودی، event.respondWith()
از داخل یک کنترل کننده رویداد fetch
، مانند این فراخوانی کنید:
// fetch event handler in your service worker file
self.addEventListener("fetch", event => {
const response = .... // a response or a Promise of response
event.respondWith(response);
});
شما باید respondWith()
به طور همزمان فراخوانی کنید و باید یک شی Response را برگردانید. اما نمیتوانید پس از اتمام واکشی واکشی کنترلکننده رویداد، مانند یک تماس همگامسازی respondWith()
را فراخوانی کنید. اگر باید منتظر پاسخ کامل باشید، می توانید یک Promise را به respondWith()
ارسال کنید که با یک Response حل می شود.
ایجاد پاسخ
به لطف Fetch API ، میتوانید پاسخهای HTTP را در کد جاوا اسکریپت خود ایجاد کنید، و آن پاسخها را میتوان با استفاده از Cache Storage API در حافظه پنهان ذخیره کرد و به گونهای که گویی از یک وب سرور میآیند، بازگردانده میشوند.
برای ایجاد یک پاسخ، یک شی Response
جدید ایجاد کنید و بدنه آن و گزینه هایی مانند وضعیت و هدرها را تنظیم کنید:
const simpleResponse = new Response("Body of the HTTP response");
const options = {
status: 200,
headers: {
'Content-type': 'text/html'
}
};
const htmlResponse = new Response("<b>HTML</b> content", options)
پاسخ از حافظه پنهان
اکنون که میدانید چگونه پاسخهای HTTP را از یک سرویسدهنده ارائه کنید، وقت آن است که از رابط ذخیرهسازی حافظه پنهان برای ذخیره داراییها در دستگاه استفاده کنید.
می توانید از API ذخیره سازی کش استفاده کنید تا بررسی کنید که آیا درخواست دریافت شده از PWA در حافظه نهان موجود است یا خیر، و اگر وجود دارد، با آن به respondWith()
پاسخ دهید. برای انجام این کار، ابتدا باید درون کش جستجو کنید. تابع match()
که در رابط caches
سطح بالا موجود است، همه فروشگاهها را در مبدا یا روی یک شی کش باز جستجو میکند.
تابع match()
یک درخواست HTTP یا یک URL را به عنوان آرگومان دریافت می کند و وعده ای را برمی گرداند که با Response مرتبط با کلید مربوطه حل می شود.
// Global search on all caches in the current origin
caches.match(urlOrRequest).then(response => {
console.log(response ? response : "It's not in the cache");
});
// Cache-specific search
caches.open("pwa-assets").then(cache => {
cache.match(urlOrRequest).then(response => {
console.log(response ? response : "It's not in the cache");
});
});
استراتژی های ذخیره سازی
ارائه فایلها فقط از حافظه پنهان مرورگر برای هر موردی مناسب نیست. به عنوان مثال، کاربر یا مرورگر می تواند کش را خارج کند. به همین دلیل است که باید استراتژی های خود را برای ارائه دارایی برای PWA خود تعریف کنید. شما محدود به یک استراتژی کش نیستید. شما می توانید الگوهای مختلف را برای الگوهای URL مختلف تعریف کنید. برای مثال، میتوانید یک استراتژی برای حداقل داراییهای UI، استراتژی دیگر برای تماسهای API و استراتژی سوم برای URLهای تصویر و داده داشته باشید. برای انجام این کار، event.request.url
در ServiceWorkerGlobalScope.onfetch
بخوانید و آن را از طریق عبارات منظم یا یک الگوی URL تجزیه کنید. (در زمان نوشتن، الگوی URL در همه سیستم عامل ها پشتیبانی نمی شود).
رایج ترین استراتژی ها عبارتند از:
- ابتدا کش
- ابتدا یک پاسخ ذخیره شده در حافظه پنهان را جستجو می کند و اگر پاسخی پیدا نشد به شبکه باز می گردد.
- شبکه اول
- ابتدا از شبکه درخواست پاسخ می دهد و اگر هیچ پاسخی برگردانده نشد، پاسخ را در حافظه پنهان بررسی می کند.
- قدیمی در حالی که اعتبار مجدد
- پاسخی را از حافظه پنهان ارائه میکند، در حالی که در پسزمینه آخرین نسخه را درخواست میکند و آن را برای دفعه بعدی درخواست دارایی در حافظه پنهان ذخیره میکند.
- فقط شبکه
- همیشه با یک پاسخ از شبکه یا خطا پاسخ می دهد. کش هرگز مورد مشورت قرار نمی گیرد.
- فقط حافظه پنهان
- همیشه با یک پاسخ از حافظه پنهان یا خطاها پاسخ می دهد. شبکه هرگز مورد مشورت قرار نخواهد گرفت. دارایی هایی که با استفاده از این استراتژی ارائه می شوند باید قبل از درخواست به حافظه پنهان اضافه شوند.
ابتدا کش
با استفاده از این استراتژی، سرویسکار به دنبال درخواست تطبیق در حافظه پنهان میگردد و در صورت ذخیرهسازی، پاسخ مربوطه را برمیگرداند. در غیر این صورت، پاسخ را از شبکه بازیابی می کند (به صورت اختیاری، به روز رسانی حافظه پنهان برای تماس های بعدی). اگر نه پاسخ کش وجود داشته باشد و نه پاسخ شبکه، درخواست با خطا مواجه می شود. از آنجایی که ارائه داراییها بدون رفتن به شبکه سریعتر است، این استراتژی عملکرد را بر تازگی ترجیح میدهد.
self.addEventListener("fetch", event => {
event.respondWith(
caches.match(event.request)
.then(cachedResponse => {
// It can update the cache to serve updated content on the next request
return cachedResponse || fetch(event.request);
}
)
)
});
اول شبکه
این استراتژی آینه استراتژی Cache First است. بررسی میکند که آیا درخواست میتواند از شبکه انجام شود یا خیر، و اگر نمیتواند، سعی میکند آن را از حافظه پنهان بازیابی کند. ابتدا کش را دوست داشته باشید. اگر نه پاسخ شبکه و نه پاسخ کش وجود داشته باشد، درخواست با خطا مواجه می شود. دریافت پاسخ از شبکه معمولا کندتر از دریافت آن از حافظه پنهان است، این استراتژی به جای عملکرد، محتوای به روز شده را در اولویت قرار می دهد.
self.addEventListener("fetch", event => {
event.respondWith(
fetch(event.request)
.catch(error => {
return caches.match(event.request) ;
})
);
});
بیات در حالی که اعتبار مجدد
استراتژی stale while revalidate یک پاسخ ذخیره شده را بلافاصله برمی گرداند، سپس شبکه را برای به روز رسانی بررسی می کند و در صورت یافتن پاسخ ذخیره شده جایگزین آن می شود. این استراتژی همیشه یک درخواست شبکه می دهد، زیرا حتی اگر یک منبع ذخیره شده در حافظه پنهان پیدا شود، سعی می کند آنچه را که در حافظه پنهان بود با آنچه از شبکه دریافت شده است، به روز کند تا در درخواست بعدی از نسخه به روز شده استفاده کند. بنابراین، این استراتژی راهی را برای شما فراهم می کند تا از سرویس سریع اولین استراتژی کش بهره مند شوید و کش را در پس زمینه به روز کنید.
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request).then(cachedResponse => {
const networkFetch = fetch(event.request).then(response => {
// update the cache with a clone of the network response
const responseClone = response.clone()
caches.open(url.searchParams.get('name')).then(cache => {
cache.put(event.request, responseClone)
})
return response
}).catch(function (reason) {
console.error('ServiceWorker fetch failed: ', reason)
})
// prioritize cached response over network
return cachedResponse || networkFetch
}
)
)
})
فقط شبکه
استراتژی تنها شبکه شبیه به نحوه رفتار مرورگرها بدون سرویس کار یا API حافظه کش است. درخواستها فقط در صورتی منبعی را برمیگردانند که بتوان آن را از شبکه واکشی کرد. این اغلب برای منابعی مانند درخواستهای API فقط آنلاین مفید است.
فقط کش
استراتژی تنها کش تضمین می کند که درخواست ها هرگز به شبکه نمی روند. تمام درخواستهای دریافتی با یک آیتم حافظه پنهان از قبل پر شده پاسخ داده میشوند. کد زیر از کنترلکننده رویداد fetch
با روش match
حافظه پنهان برای پاسخگویی به حافظه پنهان استفاده میکند:
self.addEventListener("fetch", event => {
event.respondWith(caches.match(event.request));
});
استراتژی های سفارشی
در حالی که موارد بالا استراتژیهای رایج ذخیرهسازی هستند، شما مسئول سرویسدهنده خود و نحوه رسیدگی به درخواستها هستید. اگر هیچ یک از اینها برای نیازهای شما کار نمی کند، خود را ایجاد کنید.
برای مثال، میتوانید از یک استراتژی شبکه اول با مهلت زمانی برای اولویتبندی محتوای بهروزرسانی شده استفاده کنید، اما تنها در صورتی که پاسخ در آستانهای که شما تعیین کردهاید ظاهر شود. همچنین میتوانید یک پاسخ ذخیرهشده را با یک پاسخ شبکه ادغام کنید و یک پاسخ پیچیده از سرویسکار بسازید.
به روز رسانی دارایی ها
به روز نگه داشتن دارایی های ذخیره شده PWA شما می تواند یک چالش باشد. در حالی که استراتژی قدیمی اعتبارسنجی مجدد یکی از راههای انجام این کار است، این تنها راه نیست. در فصل بهروزرسانی ، تکنیکهای مختلفی را برای بهروزرسانی محتوا و داراییهای برنامهتان یاد خواهید گرفت.