وقتی به کارگران خدماتی فکر می کنیم چگونه فکر کنیم.
کارکنان خدمات قدرتمند هستند و کاملاً ارزش یادگیری دارند. آنها به شما اجازه می دهند سطح کاملا جدیدی از تجربه را به کاربران خود ارائه دهید. سایت شما می تواند فورا بارگیری شود. می تواند به صورت آفلاین کار کند. میتوان آن را بهعنوان یک برنامه مخصوص پلتفرم نصب کرد و هر ذره زیبایی را احساس کرد - اما با دسترسی و آزادی وب.
اما کارگران خدماتی بر خلاف هر چیزی هستند که اکثر ما توسعه دهندگان وب به آن عادت کرده ایم. آنها با یک منحنی یادگیری شیب دار و تعدادی مشکل ارائه می شوند که باید مراقب آنها باشید.
من و Google Developers اخیراً در پروژه ای همکاری کردیم - Service Workies - یک بازی رایگان برای درک کارکنان خدمات. در حین ساختن آن و کار با کارکنان خدماتی پیچیده، با چند مشکل برخورد کردم. چیزی که بیش از همه به من کمک کرد این بود که مشتی استعاره تصویری را ارائه دهم. در این پست ما این مدلهای ذهنی را بررسی میکنیم و مغزمان را در اطراف ویژگیهای متناقض که کارکنان خدمات را هم حیلهگر و هم عالی میسازد، میپیچیم.
یکسان، اما متفاوت
هنگام کدنویسی کارمند خدمات خود، بسیاری از چیزها آشنا به نظر می رسد. می توانید از ویژگی های زبان جدید جاوا اسکریپت مورد علاقه خود استفاده کنید. شما به رویدادهای چرخه زندگی مانند رویدادهای رابط کاربری گوش می دهید. شما جریان کنترل را با وعده هایی که به آن عادت کرده اید مدیریت می کنید.
اما سایر رفتارهای کارکنان خدمات باعث می شود که سر خود را با سردرگمی خارانید. به خصوص زمانی که صفحه را رفرش می کنید و تغییرات کد خود را اعمال نمی کنید.
یک لایه جدید
به طور معمول هنگام ساخت یک سایت شما فقط باید به دو لایه فکر کنید: مشتری و سرور. کارگر سرویس یک لایه کاملاً جدید است که در وسط قرار دارد.
به کارگر خدماتی خود به عنوان نوعی افزونه مرورگر فکر کنید — افزونه ای که سایت شما می تواند در مرورگر کاربر نصب کند. پس از نصب، سرویسکار مرورگر سایت شما را با یک لایه میانی قدرتمند گسترش میدهد . این لایه سرویسکار میتواند تمام درخواستهایی را که سایت شما ارسال میکند رهگیری کرده و رسیدگی کند.
لایه Service Worker چرخه حیات خود را مستقل از تب مرورگر دارد. یک تازهسازی ساده صفحه برای بهروزرسانی یک سرویسکار کافی نیست، درست مثل اینکه انتظار ندارید یک بازخوانی صفحه کدهای مستقر در سرور را بهروزرسانی کند. هر لایه قوانین منحصر به فرد خود را برای به روز رسانی دارد.
در بازی Service Workies ما جزئیات زیادی از چرخه عمر کارگر خدمات را پوشش میدهیم و به شما تمرین زیادی برای کار با آن میدهیم.
قدرتمند، اما محدود
وجود یک کارگر خدماتی در سایت شما مزایای باورنکردنی را به همراه دارد. سایت شما می تواند:
- حتی زمانی که کاربر آفلاین است، بدون نقص کار کنید
- از طریق کش کردن، بهبود عملکرد گسترده ای را به دست آورید
- از اعلان های فشار استفاده کنید
- به عنوان PWA نصب شود
تا آنجایی که کارگران خدمات می توانند انجام دهند، طراحی آنها محدود است. آنها نمی توانند هیچ کاری همزمان یا در همان رشته سایت شما انجام دهند. بنابراین این به معنای عدم دسترسی به:
- محل ذخیره سازی
- DOM
- پنجره
خبر خوب این است که راههای انگشت شماری وجود دارد که صفحه شما میتواند با سرویسدهنده خود ارتباط برقرار کند، از جمله postMessage
مستقیم، کانالهای پیام یک به یک و کانالهای پخش یک به چند.
عمر طولانی، اما کوتاه مدت
یک سرویس دهنده فعال حتی پس از اینکه کاربر سایت شما را ترک کرد یا برگه را ببندد به زندگی خود ادامه می دهد. مرورگر این سرویس دهنده را در اطراف نگه می دارد تا دفعه بعد که کاربر به سایت شما بازگردد آماده باشد. قبل از اینکه اولین درخواست انجام شود، سرویسکار فرصتی پیدا میکند تا آن را رهگیری کند و صفحه را کنترل کند. این همان چیزی است که به یک سایت اجازه می دهد به صورت آفلاین کار کند—کارگر خدمات می تواند نسخه کش شده خود صفحه را ارائه دهد، حتی اگر کاربر به اینترنت متصل نباشد.
در Service Workies ما این مفهوم را با Kolohe (یک کارگر خدمات دوستانه) در حال رهگیری و رسیدگی به درخواستها تجسم میکنیم.
متوقف شد
علیرغم اینکه کارگران خدماتی جاودانه به نظر می رسند، تقریباً در هر زمانی می توان آنها را متوقف کرد . مرورگر نمیخواهد منابع را برای یک سرویسکار که در حال حاضر کاری انجام نمیدهد هدر دهد. متوقف شدن با فسخ یکسان نیست—کارگر سرویس همچنان نصب و فعال میشود. فقط خوابیده دفعه بعد که به آن نیاز است (به عنوان مثال، برای رسیدگی به یک درخواست)، مرورگر آن را بیدار می کند.
صبر کنید تا
به دلیل امکان دائمی به خواب رفتن، کارمند خدمات شما به راهی نیاز دارد تا به مرورگر اطلاع دهد که در حال انجام کار مهمی است و تمایلی به چرت زدن ندارد. اینجاست که event.waitUntil()
وارد عمل می شود. این روش چرخه عمری که در آن استفاده میشود را افزایش میدهد، و آن را از توقف و انتقال به مرحله بعدی چرخه عمر تا زمانی که ما آماده شویم، حفظ میکند. این به ما زمان می دهد تا کش ها را راه اندازی کنیم، منابع را از شبکه واکشی کنیم و غیره.
این مثال به مرورگر میگوید که تا زمانی که حافظه پنهان assets
ایجاد نشده و با تصویر یک شمشیر پر نشده باشد، سرویسکار ما نصب را تمام نکرده است:
self.addEventListener("install", event => {
event.waitUntil(
caches.open("assets").then(cache => {
return cache.addAll(["/weapons/sword/blade.png"]);
})
);
});
مراقب وضعیت جهانی باشید
هنگامی که این شروع/توقف اتفاق میافتد، دامنه جهانی کارگر سرویس بازنشانی میشود. بنابراین مراقب باشید که از هیچ حالت جهانی در سرویسکار خود استفاده نکنید وگرنه دفعه بعد که دوباره بیدار شد و حالتی متفاوت از آنچه انتظار داشت، ناراحت خواهید شد.
این مثال را در نظر بگیرید که از یک حالت جهانی استفاده می کند:
const favoriteNumber = Math.random();
let hasHandledARequest = false;
self.addEventListener("fetch", event => {
console.log(favoriteNumber);
console.log(hasHandledARequest);
hasHandledARequest = true;
});
در هر درخواست، این سرویسگر شمارهای را ثبت میکند - فرض کنید 0.13981866382421893
. متغیر hasHandledARequest
نیز به true
تغییر می کند. اکنون سرویسکار برای مدتی بیحرکت مینشیند، بنابراین مرورگر آن را متوقف میکند. دفعه بعد که درخواستی وجود داشت، دوباره به کارمند سرویس نیاز است، بنابراین مرورگر آن را بیدار می کند. فیلمنامه آن دوباره ارزیابی می شود. اکنون hasHandledARequest
به false
بازنشانی شده است و favoriteNumber
چیزی کاملاً متفاوت است 0.5907281835659033
.
شما نمی توانید به حالت ذخیره شده در یک سرویس دهنده تکیه کنید. همچنین، ایجاد نمونههایی از مواردی مانند کانالهای پیام میتواند باعث ایجاد اشکال شود: هر بار که سرویسکار متوقف/شروع میکند، یک نمونه کاملاً جدید دریافت میکنید.
در فصل 3 Service Workies، ما کارمند سرویس متوقف شده خود را در حالی که منتظر بیدار شدن است، رنگ خود را از دست داده است.
با هم، اما جدا
صفحه شما را فقط میتوان توسط یک سرویسدهنده در یک زمان کنترل کرد . اما می تواند دو سرویس دهنده را به طور همزمان نصب کند . وقتی شما تغییری در کد سرویسکار خود ایجاد میکنید و صفحه را بازخوانی میکنید، در واقع به هیچ وجه سرویسکار خود را ویرایش نمیکنید. کارگران خدماتی تغییر ناپذیر هستند. شما در عوض یک محصول کاملا جدید می سازید. این سرویسکار جدید (بیایید آن را SW2 بنامیم) نصب میشود اما هنوز فعال نمیشود. باید منتظر بماند تا سرویسکار فعلی (SW1) خاتمه یابد (زمانی که کاربر سایت شما را ترک میکند).
درگیر شدن با حافظه پنهان یک کارگر خدماتی دیگر
در حین نصب، SW2 میتواند موارد را راهاندازی کند - معمولاً حافظه پنهان ایجاد و پر میکند. اما مراقب باشید: این کارگر خدماتی جدید به همه چیزهایی که سرویسکار فعلی به آن دسترسی دارد دسترسی دارد. اگر مراقب نباشید، کارمند خدمات انتظار جدید شما واقعاً میتواند اوضاع را برای خدمتکار فعلی شما به هم بزند. چند مثال که ممکن است برای شما دردسر ایجاد کند:
- SW2 می تواند کشی را که SW1 به طور فعال از آن استفاده می کند حذف کند.
- SW2 میتواند محتویات حافظه پنهانی را که SW1 استفاده میکند ویرایش کند و باعث شود SW1 با داراییهایی پاسخ دهد که صفحه انتظارش را ندارد.
رد شدن از skipWaiting
یک سرویسکار همچنین میتواند از روش مخاطرهآمیز skipWaiting()
برای کنترل صفحه به محض اتمام نصب استفاده کند. این به طور کلی ایده بدی است مگر اینکه عمداً بخواهید یک کارگر خدمات کالسکه را جایگزین کنید. سرویسکار جدید ممکن است از منابع بهروزرسانیشدهای استفاده میکند که صفحه فعلی انتظارش را ندارد، که منجر به خطاها و اشکالات میشود.
تمیز کردن را شروع کنید
راه برای جلوگیری از هجمه کردن کارکنان سرویس شما این است که مطمئن شوید که از کش های مختلف استفاده می کنند. سادهترین راه برای انجام این کار، نسخهسازی نامهای کش است که استفاده میکنند.
const version = 1;
const assetCacheName = `assets-${version}`;
self.addEventListener("install", event => {
caches.open(assetCacheName).then(cache => {
// confidently do stuff with your very own cache
});
});
وقتی یک سرویسکار جدید را مستقر میکنید، version
را بهگونهای افزایش میدهید که با یک کش کاملاً مجزا از سرویسکار قبلی، آنچه را که نیاز دارد انجام دهد.
تمیز تمام شود
هنگامی که کارمند سرویس شما به حالت activated
میرسد، میدانید که کار را به دست گرفته است و سرویسکار قبلی مازاد بر کار است. در این مرحله مهم است که بعد از سرویسکار قدیمی تمیز کنید. نه تنها به محدودیتهای ذخیرهسازی حافظه پنهان کاربران شما احترام میگذارد، بلکه میتواند از بروز اشکالات غیرعمدی نیز جلوگیری کند.
متد caches.match()
یک میانبر است که اغلب برای بازیابی یک آیتم از هر حافظه پنهانی که در آن تطابق وجود دارد استفاده می شود. اما از طریق کش ها به ترتیب ایجاد شده تکرار می شود. بنابراین فرض کنید شما دو نسخه از یک فایل اسکریپت app.js
را در دو کش مختلف دارید- assets-1
و assets-2
. صفحه شما منتظر اسکریپت جدیدتری است که در assets-2
ذخیره شده است. اما اگر کش قدیمی را حذف نکرده باشید، caches.match('app.js')
حافظه قبلی را از assets-1
برمی گرداند و به احتمال زیاد سایت شما را خراب می کند.
تنها چیزی که برای پاکسازی پس از سرویسکاران قبلی لازم است، حذف حافظه پنهانی است که سرویسکار جدید به آن نیاز ندارد:
const version = 2;
const assetCacheName = `assets-${version}`;
self.addEventListener("activate", event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames.map(cacheName => {
if (cacheName !== assetCacheName){
return caches.delete(cacheName);
}
});
);
});
);
});
جلوگیری از دزدی کارکنان خدماتی شما کمی کار و انضباط می خواهد، اما ارزش زحمت را دارد.
طرز فکر کارکنان خدماتی
داشتن طرز فکر صحیح در حین فکر کردن به کارگران خدماتی به شما کمک می کند تا با اعتماد به نفس خود را بسازید. هنگامی که از آنها استفاده کنید، می توانید تجربیات باورنکردنی را برای کاربران خود ایجاد کنید.
اگر می خواهید همه اینها را با انجام یک بازی درک کنید، پس خوش شانس هستید! به بازی Service Workies بروید، جایی که روشهای کارگر خدمات برای کشتن جانوران آفلاین را یاد خواهید گرفت.