سخت است بدانید که کارگران بدون درک چرخه زندگی آنها چه خدماتی انجام می دهند. عملکرد درونی آنها مبهم و حتی خودسرانه به نظر می رسد. به یاد داشته باشید که - مانند هر API مرورگر دیگری - رفتارهای کارکنان سرویس به خوبی تعریف شده، مشخص شده است و برنامه های آفلاین را ممکن می کند، در حالی که به روز رسانی را بدون ایجاد اختلال در تجربه کاربر تسهیل می کند.
قبل از فرو رفتن در Workbox، مهم است که چرخه عمر کارگر خدمات را درک کنید تا کاری که Workbox انجام می دهد منطقی باشد.
تعریف اصطلاحات
قبل از ورود به چرخه عمر کارگر خدماتی، ارزش آن را دارد که برخی از اصطلاحات را در مورد نحوه عملکرد آن چرخه تعریف کنیم.
کنترل و دامنه
ایده کنترل برای درک نحوه عملکرد کارکنان خدمات بسیار مهم است. صفحهای که توسط یک سرویسکار کنترل میشود، صفحهای است که به یک سرویسگر اجازه میدهد تا درخواستهای شبکه را از طرف خود رهگیری کند. کارگر خدمات حضور دارد و قادر به انجام کار برای صفحه در محدوده معین است.
دامنه
محدوده یک کارگر خدماتی با موقعیت مکانی آن در وب سرور تعیین می شود. اگر یک سرویسکار در صفحهای که در /subdir/index.html
قرار دارد و در /subdir/sw.js
قرار دارد اجرا میشود، محدوده سرویسکار /subdir/
است. برای مشاهده مفهوم دامنه در عمل، این مثال را بررسی کنید:
- به https://service-worker-scope-viewer.glitch.me/subdir/index.html بروید. پیامی ظاهر می شود که می گوید هیچ سرویس دهنده ای صفحه را کنترل نمی کند. با این حال، آن صفحه یک سرویسکار را از
https://service-worker-scope-viewer.glitch.me/subdir/sw.js
ثبت میکند. - صفحه را دوباره بارگیری کنید. از آنجایی که سرویسکار ثبتشده است و اکنون فعال است، صفحه را کنترل میکند. فرمی حاوی محدوده کارمند سرویس، وضعیت فعلی و URL آن قابل مشاهده خواهد بود. توجه: نیاز به بارگذاری مجدد صفحه ربطی به دامنه ندارد، بلکه چرخه عمر کارگر سرویس است که بعدا توضیح داده خواهد شد.
- اکنون به https://service-worker-scope-viewer.glitch.me/index.html بروید. حتی با وجود اینکه یک کارگر خدماتی در این مبدا ثبت شده است، هنوز پیامی وجود دارد که میگوید هیچ سرویسکار فعلی وجود ندارد. به این دلیل که این صفحه در محدوده خدمات ثبت نام شده نیست.
محدوده صفحاتی را که کارگر خدمات کنترل می کند محدود می کند. در این مثال، این بدان معناست که سرویسکار بارگیری شده از /subdir/sw.js
فقط میتواند صفحات واقع در /subdir/
یا زیردرخت آن را کنترل کند.
موارد بالا نحوه عملکرد محدوده به طور پیش فرض است، اما حداکثر محدوده مجاز را می توان با تنظیم هدر پاسخ Service-Worker-Allowed
و همچنین ارسال یک گزینه scope
به متد register
لغو کرد.
مگر اینکه دلیل بسیار خوبی برای محدود کردن محدوده سرویس کارگر به زیرمجموعهای از مبدا وجود داشته باشد، یک سرویسکار را از دایرکتوری ریشه وب سرور بارگیری کنید تا دامنه آن تا حد امکان گسترده باشد و نگران Service-Worker-Allowed
نباشید. هدر Service-Worker-Allowed
اینطوری برای همه خیلی ساده تر است.
مشتری
وقتی گفته می شود که یک سرویس دهنده یک صفحه را کنترل می کند، در واقع یک مشتری را کنترل می کند. کلاینت هر صفحه باز است که URL آن در محدوده آن سرویسکار قرار میگیرد. به طور خاص، اینها نمونه هایی از یک WindowClient
هستند.
چرخه زندگی یک کارگر خدماتی جدید
برای اینکه یک کارگر خدماتی بتواند یک صفحه را کنترل کند، ابتدا باید به اصطلاح به وجود بیاید. بیایید با آنچه اتفاق میافتد، زمانی که یک سرویسکار کاملاً جدید برای وبسایتی بدون سرویسکار فعال مستقر میشود، شروع میکنیم.
ثبت نام
ثبت نام مرحله اولیه چرخه عمر کارگر خدماتی است:
<!-- In index.html, for example: -->
<script>
// Don't register the service worker
// until the page has fully loaded
window.addEventListener('load', () => {
// Is service worker available?
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js').then(() => {
console.log('Service worker registered!');
}).catch((error) => {
console.warn('Error registering service worker:');
console.warn(error);
});
}
});
</script>
این کد روی رشته اصلی اجرا می شود و کارهای زیر را انجام می دهد:
- از آنجایی که اولین بازدید کاربر از یک وبسایت بدون سرویسکار ثبتشده انجام میشود، قبل از ثبتنام، صبر کنید تا صفحه بهطور کامل بارگیری شود. اگر سرویسدهنده چیزی را از پیش ذخیره کند، این کار از مناقشه پهنای باند جلوگیری میکند.
- اگرچه Service Worker به خوبی پشتیبانی می شود ، یک بررسی سریع به جلوگیری از خطا در مرورگرهایی که پشتیبانی نمی شود کمک می کند.
- هنگامی که صفحه به طور کامل بارگیری شد، و اگر Service Worker پشتیبانی می شود،
/sw.js
را ثبت کنید.
برخی از چیزهای کلیدی برای درک عبارتند از:
- کارکنان خدمات فقط از طریق HTTPS یا میزبان محلی در دسترس هستند.
- اگر محتویات یک سرویسکار دارای خطاهای نحوی باشد، ثبت نام انجام نمیشود و کارمند سرویس دور انداخته میشود.
- یادآوری: کارگران خدمات در یک محدوده عمل می کنند. در اینجا، دامنه کل مبدا است، همانطور که از دایرکتوری ریشه بارگیری شده است.
- هنگامی که ثبت نام شروع می شود، وضعیت سرویس دهنده روی
'installing'
تنظیم می شود.
پس از اتمام ثبت نام، نصب شروع می شود.
نصب و راه اندازی
یک سرویسکار پس از ثبتنام، رویداد install
خود را فعال میکند. install
فقط یک بار به ازای هر سرویس دهنده فراخوانی می شود و تا زمانی که به روز نشود دوباره فعال نمی شود. یک تماس برگشتی برای رویداد install
را می توان با addEventListener
در محدوده کارگر ثبت کرد:
// /sw.js
self.addEventListener('install', (event) => {
const cacheKey = 'MyFancyCacheName_v1';
event.waitUntil(caches.open(cacheKey).then((cache) => {
// Add all the assets in the array to the 'MyFancyCacheName_v1'
// `Cache` instance for later use.
return cache.addAll([
'/css/global.bc7b80b7.css',
'/css/home.fe5d0b23.css',
'/js/home.d3cc4ba4.js',
'/js/jquery.43ca4933.js'
]);
}));
});
این یک نمونه Cache
جدید ایجاد می کند و دارایی ها را پیش کش می کند. بعداً فرصتهای زیادی برای صحبت در مورد precach کردن خواهیم داشت، بنابراین بیایید روی نقش event.waitUntil
تمرکز کنیم.waitUntil. event.waitUntil
قولی را می پذیرد و منتظر می ماند تا آن قول حل شود. در این مثال، آن وعده دو کار ناهمزمان انجام می دهد:
- یک نمونه
Cache
جدید با نام'MyFancyCache_v1'
ایجاد می کند. - پس از ایجاد کش، آرایهای از URLهای دارایی با استفاده از روش
addAll
ناهمزمان آن، از پیش ذخیره میشوند.
در صورتی که قول(های) به event.waitUntil
منتقل شود، نصب با شکست مواجه می شود. waitUntil رد شود. اگر این اتفاق بیفتد، کارگر خدماتی کنار گذاشته می شود.
اگر وعدهها حل شود ، نصب با موفقیت انجام میشود و وضعیت سرویسکار به 'installed'
تغییر میکند و سپس فعال میشود.
فعال سازی
اگر ثبتنام و نصب با موفقیت انجام شود، سرویسکار فعال میشود، و وضعیت آن به 'activating'
تبدیل میشود. کار را میتوان در حین فعالسازی در رویداد activate
سرویسکار انجام داد. یک کار معمولی در این رویداد، هرس کردن حافظههای پنهان قدیمی است، اما برای یک سرویسکار کاملاً جدید، این موضوع فعلاً مرتبط نیست و زمانی که در مورد بهروزرسانیهای سرویسکار صحبت میکنیم، بیشتر خواهد شد.
برای سرویسکاران جدید، بلافاصله پس از موفقیت آمیز بودن install
، آتش را activate
. پس از اتمام فعالسازی، وضعیت سرویسکار 'activated'
میشود. توجه داشته باشید که بهطور پیشفرض، سرویسکار جدید کنترل صفحه را تا زمان پیمایش بعدی یا بهروزرسانی صفحه آغاز نمیکند.
رسیدگی به بهروزرسانیهای کارکنان خدمات
هنگامی که اولین سرویسکار مستقر شد، احتمالاً باید بعداً بهروزرسانی شود. به عنوان مثال، اگر تغییراتی در مدیریت درخواست یا منطق پیش کش رخ دهد، ممکن است نیاز به به روز رسانی باشد.
هنگامی که به روز رسانی اتفاق می افتد
زمانی که:
- کاربر به صفحه ای در محدوده کارمند خدمات هدایت می شود.
-
navigator.serviceWorker.register()
با یک URL متفاوت از سرویس کارگر نصب شده فعلی فراخوانی می شود — اما URL یک سرویس دهنده را تغییر ندهید ! -
navigator.serviceWorker.register()
با همان URL به عنوان service worker نصب شده فراخوانی می شود، اما با دامنه متفاوت. باز هم، در صورت امکان، با حفظ دامنه در ریشه یک مبدا از این امر اجتناب کنید. - وقتی رویدادهایی مانند
'push'
یا'sync'
در 24 ساعت گذشته راهاندازی شدهاند — اما هنوز نگران این رویدادها نباشید.
چگونه به روز رسانی اتفاق می افتد
دانستن اینکه چه زمانی مرورگر یک سرویسکار را بهروزرسانی میکند، مهم است، اما «چگونه» نیز مهم است. با فرض اینکه URL یا محدوده کارمند سرویس بدون تغییر باشد، یک سرویسکار نصب شده در حال حاضر تنها در صورتی به نسخه جدید به روز می شود که محتوای آن تغییر کرده باشد.
مرورگرها تغییرات را به چند روش تشخیص می دهند:
- هر گونه تغییر بایت به بایت در اسکریپت های درخواست شده توسط
importScripts
، در صورت وجود. - هر گونه تغییر در کد سطح بالای کارمند خدمات که بر اثر انگشتی که مرورگر از آن ایجاد کرده است تأثیر می گذارد.
مرورگر در اینجا کارهای سنگین زیادی انجام می دهد. برای اطمینان از اینکه مرورگر تمام آنچه را که برای شناسایی مطمئن تغییرات در محتویات یک سرویس دهنده نیاز دارد، دارد، به حافظه پنهان HTTP نگویید که روی آن نگه دارد و نام فایل آن را تغییر ندهید. مرورگر بهطور خودکار بررسیهای بهروزرسانی را زمانی انجام میدهد که به صفحه جدیدی در محدوده یک سرویسدهنده پیمایش میشود.
راهاندازی دستی بررسیهای بهروزرسانی
در مورد به روز رسانی ها، منطق ثبت نام به طور کلی نباید تغییر کند. با این حال، یک استثنا ممکن است این باشد که جلسات در یک وب سایت طولانی مدت باشند. این می تواند در برنامه های تک صفحه ای اتفاق بیفتد که در آن درخواست های ناوبری نادر است، زیرا برنامه معمولاً در شروع چرخه عمر برنامه با یک درخواست ناوبری مواجه می شود. در چنین شرایطی، بهروزرسانی دستی میتواند در رشته اصلی فعال شود:
navigator.serviceWorker.ready.then((registration) => {
registration.update();
});
برای وبسایتهای سنتی، یا در هر موردی که جلسات کاربر طولانی نیست، احتمالاً بهروزرسانی دستی لازم نیست.
نصب و راه اندازی
هنگام استفاده از یک بستهکننده برای تولید داراییهای ثابت، آن داراییها حاوی هشهایی در نام خود هستند، مانند framework.3defa9d2.js
. فرض کنید برخی از آن داراییها برای دسترسی آفلاین بعداً ذخیره شدهاند. برای این کار نیاز به بهروزرسانی کارگر سرویس برای پیشکش کردن داراییهای بهروزرسانی شده دارد:
self.addEventListener('install', (event) => {
const cacheKey = 'MyFancyCacheName_v2';
event.waitUntil(caches.open(cacheKey).then((cache) => {
// Add all the assets in the array to the 'MyFancyCacheName_v2'
// `Cache` instance for later use.
return cache.addAll([
'/css/global.ced4aef2.css',
'/css/home.cbe409ad.css',
'/js/home.109defa4.js',
'/js/jquery.38caf32d.js'
]);
}));
});
دو چیز با اولین مثال رویداد install
قبلی متفاوت است:
- یک نمونه
Cache
جدید با کلید'MyFancyCacheName_v2'
ایجاد می شود. - نام دارایی های پیش ذخیره شده تغییر کرده است.
نکته ای که باید به آن توجه داشت این است که یک سرویس کار به روز شده در کنار سرویس قبلی نصب می شود. این بدان معناست که سرویسکار قدیمی هنوز تمام صفحات باز را کنترل میکند و پس از نصب، صفحه جدید وارد حالت انتظار میشود تا زمانی که فعال شود.
به طور پیشفرض، یک سرویسکار جدید زمانی فعال میشود که هیچ مشتری توسط سرویسکار قدیمی کنترل نشود. این زمانی اتفاق می افتد که تمام برگه های باز برای وب سایت مربوطه بسته شود.
فعال سازی
وقتی یک سرویسکار بهروزرسانی شده نصب میشود و مرحله انتظار به پایان میرسد، فعال میشود و سرویسکار قدیمی کنار گذاشته میشود. یک کار معمولی که در رویداد activate
یک سرویس کار به روز انجام می شود، هرس کردن حافظه های پنهان قدیمی است. با دریافت کلیدهای تمام نمونه های Cache
باز با caches.keys
و حذف کش هایی که در لیست مجاز تعریف شده با caches.delete
نیستند، کش های قدیمی را حذف کنید:
self.addEventListener('activate', (event) => {
// Specify allowed cache keys
const cacheAllowList = ['MyFancyCacheName_v2'];
// Get all the currently active `Cache` instances.
event.waitUntil(caches.keys().then((keys) => {
// Delete all caches that aren't in the allow list:
return Promise.all(keys.map((key) => {
if (!cacheAllowList.includes(key)) {
return caches.delete(key);
}
}));
}));
});
کش های قدیمی خود را مرتب نمی کنند. ما باید خودمان این کار را انجام دهیم یا در خطر فراتر رفتن از سهمیه ذخیره سازی هستیم. از آنجایی که 'MyFancyCacheName_v1'
از اولین سرویسکار قدیمی است، فهرست مجاز حافظه پنهان بهروزرسانی میشود تا 'MyFancyCacheName_v2'
را مشخص کند، که حافظههای پنهان را با نام دیگری حذف میکند.
رویداد activate
پس از حذف حافظه پنهان قدیمی به پایان می رسد. در این مرحله سرویسکار جدید کنترل صفحه را در دست میگیرد و در نهایت جایگزین صفحه قبلی میشود!
چرخه زندگی همیشه ادامه دارد
چه از Workbox برای رسیدگی به استقرار و بهروزرسانیهای سرویسکار استفاده شود، چه از Service Worker API مستقیماً استفاده شود، برای درک چرخه عمر سرویسکار مفید است. با این درک، رفتارهای کارکنان خدماتی باید بیشتر منطقی به نظر برسد تا مرموز.
برای کسانی که علاقه مند به بررسی عمیق تر این موضوع هستند، ارزش بررسی این مقاله توسط جیک آرچیبالد را دارد. تفاوتهای ظریفی در نحوه انجام کل رقص در چرخه عمر سرویس وجود دارد، اما قابل دانستن است ، و این دانش در هنگام استفاده از Workbox بسیار زیاد خواهد بود.