بارگیری فوری برنامه های وب با معماری پوسته برنامه

پوسته برنامه حداقل HTML، CSS و جاوا اسکریپت است که یک رابط کاربری را تامین می کند. پوسته برنامه باید:

  • سریع بارگیری کنید
  • کش شود
  • نمایش پویا محتوا

پوسته برنامه راز عملکرد قابل اعتماد خوب است. پوسته برنامه خود را مانند بسته کدی در نظر بگیرید که اگر در حال ساختن یک برنامه بومی بودید، در یک فروشگاه برنامه منتشر می کردید. این باری است که برای بلند شدن از زمین لازم است، اما ممکن است تمام داستان نباشد. این رابط کاربری شما را محلی نگه می دارد و محتوا را به صورت پویا از طریق یک API جذب می کند.

پوسته برنامه جداسازی پوسته HTML، JS و CSS و محتوای HTML

زمینه

مقاله برنامه‌های وب پیشرفته الکس راسل توضیح می‌دهد که چگونه یک برنامه وب می‌تواند به تدریج از طریق استفاده و رضایت کاربر تغییر کند تا تجربه‌ای شبیه به برنامه بومی‌تر را با پشتیبانی آفلاین، اعلان‌های فشاری و قابلیت اضافه شدن به صفحه اصلی ارائه دهد. این بسیار به عملکرد و مزایای عملکرد سرویس دهنده و توانایی های ذخیره سازی آنها بستگی دارد. این به شما امکان می‌دهد روی سرعت تمرکز کنید و به برنامه‌های وب خود همان بارگذاری فوری و به‌روزرسانی‌های منظمی را می‌دهد که عادت داشتید در برنامه‌های بومی مشاهده کنید.

برای بهره‌گیری کامل از این قابلیت‌ها، به یک روش جدید در مورد وب‌سایت‌ها نیاز داریم: معماری پوسته برنامه .

بیایید نحوه ساختار برنامه خود را با استفاده از معماری پوسته برنامه افزوده شده سرویس‌کار بررسی کنیم. ما هم رندر سمت سرویس گیرنده و هم رندر سمت سرور را بررسی می کنیم و نمونه سرتاسری را که می توانید امروز امتحان کنید به اشتراک می گذاریم.

برای تأکید بر این نکته، مثال زیر اولین بارگذاری یک برنامه با استفاده از این معماری را نشان می دهد. به نان تست «برنامه برای استفاده آفلاین آماده است» در پایین صفحه توجه کنید. اگر بعداً به‌روزرسانی پوسته در دسترس قرار گرفت، می‌توانیم به کاربر اطلاع دهیم تا نسخه جدید را به‌روزرسانی کند.

تصویر کارگر سرویس در حال اجرا در DevTools برای پوسته برنامه

کارگران خدماتی، دوباره چه هستند؟

Service Worker اسکریپتی است که جدا از صفحه وب شما در پس زمینه اجرا می شود. به رویدادها، از جمله درخواست‌های شبکه‌ای که از صفحاتی که ارائه می‌کند و اعلان‌های ارسالی از سرور شما، پاسخ می‌دهد. یک کارگر خدماتی عمداً عمر کوتاهی دارد. وقتی رویدادی را دریافت می کند بیدار می شود و فقط تا زمانی که نیاز به پردازش آن داشته باشد اجرا می شود.

کارکنان خدمات همچنین در مقایسه با جاوا اسکریپت در یک زمینه مرور عادی، مجموعه محدودی از APIها دارند. این استاندارد برای کارگران در وب است. یک Service Worker نمی تواند به DOM دسترسی داشته باشد اما می تواند به مواردی مانند Cache API دسترسی داشته باشد و می تواند با استفاده از Fetch API درخواست های شبکه را انجام دهد. IndexedDB API و postMessage() نیز برای استفاده برای ماندگاری داده و ارسال پیام بین سرویس دهنده و صفحاتی که کنترل می کند در دسترس هستند. رویدادهای فشاری ارسال شده از سرور شما می توانند از API اطلاع رسانی برای افزایش تعامل کاربر استفاده کنند.

یک سرویس‌کار می‌تواند درخواست‌های شبکه‌ای را که از یک صفحه انجام می‌شود (که یک رویداد واکشی را در سرویس‌کار راه‌اندازی می‌کند) رهگیری کند و پاسخی را که از شبکه بازیابی شده، یا از حافظه پنهان محلی بازیابی شده، یا حتی به صورت برنامه‌نویسی ساخته شده است، بازگرداند. به طور موثر، این یک پروکسی قابل برنامه ریزی در مرورگر است. بخش دقیق این است که، صرف نظر از اینکه پاسخ از کجا می‌آید، به نظر می‌رسد که در صفحه وب هیچ دخالتی از کارکنان خدماتی وجود ندارد.

برای کسب اطلاعات بیشتر در مورد کارگران خدماتی، مقدمه ای بر کارگران خدماتی را بخوانید.

مزایای عملکرد

کارکنان خدمات برای ذخیره‌سازی آفلاین قدرتمند هستند، اما عملکرد قابل توجهی را در قالب بارگیری فوری برای بازدیدهای مکرر از سایت یا برنامه وب شما ارائه می‌دهند. می توانید پوسته برنامه خود را کش کنید تا به صورت آفلاین کار کند و محتوای آن را با استفاده از جاوا اسکریپت پر کنید.

در بازدیدهای مکرر، این به شما امکان می‌دهد بدون شبکه ، پیکسل‌های معنی‌داری را روی صفحه‌نمایش دریافت کنید، حتی اگر محتوای شما در نهایت از آنجا باشد. به این فکر کنید که نوار ابزارها و کارت‌ها را فوراً نشان می‌دهد و سپس بقیه محتوای خود را به تدریج بارگیری می‌کند.

برای آزمایش این معماری بر روی دستگاه های واقعی، نمونه پوسته برنامه خود را در WebPageTest.org اجرا کرده ایم و نتایج را در زیر نشان داده ایم.

تست 1: آزمایش روی کابل با Nexus 5 با استفاده از Chrome Dev

نمای اول برنامه باید همه منابع را از شبکه واکشی کند و تا 1.2 ثانیه به رنگ معنی‌داری دست پیدا نمی‌کند. به لطف ذخیره‌سازی سرویس‌دهنده، بازدید مجدد ما به رنگ معنی‌دار دست می‌یابد و بارگیری را در 0.5 ثانیه به‌طور کامل به پایان می‌رساند.

نمودار رنگ آزمایشی صفحه وب برای اتصال کابل

تست 2: آزمایش روی 3G با Nexus 5 با استفاده از Chrome Dev

ما همچنین می توانیم نمونه خود را با اتصال 3G کمی کندتر آزمایش کنیم. این بار در اولین بازدید 2.5 ثانیه طول می کشد تا اولین رنگ معنی دار ما باشد. 7.1 ثانیه طول می کشد تا صفحه به طور کامل بارگذاری شود. با ذخیره سرویس کارگر، بازدید مجدد ما به رنگ معنی‌دار دست می‌یابد و بارگیری را در 0.8 ثانیه به‌طور کامل به پایان می‌رساند.

نمودار رنگ آمیزی آزمایشی صفحه وب برای اتصال 3G

دیدگاه های دیگر نیز داستان مشابهی را بیان می کنند. 3 ثانیه ای را که برای رسیدن به اولین رنگ معنی دار در پوسته برنامه لازم است مقایسه کنید:

جدول زمانی را برای اولین نمایش از تست صفحه وب نقاشی کنید

به 0.9 ثانیه ای که طول می کشد زمانی که همان صفحه از کش سرویس کارگر بارگیری می شود. بیش از 2 ثانیه زمان برای کاربران نهایی ما ذخیره می شود.

جدول زمانی را برای مشاهده تکرار از تست صفحه وب رنگ کنید

برنده عملکرد مشابه و قابل اعتماد برای برنامه های خود با استفاده از معماری پوسته برنامه امکان پذیر است.

آیا کارمند خدمات از ما می خواهد که در نحوه ساختار برنامه ها تجدید نظر کنیم؟

کارکنان خدمات مستلزم برخی تغییرات ظریف در معماری برنامه هستند. به جای له کردن همه برنامه های خود در یک رشته HTML، انجام کارهایی به سبک AJAX می تواند مفید باشد. اینجا جایی است که شما یک پوسته (که همیشه در حافظه پنهان است و همیشه می تواند بدون شبکه راه اندازی شود) و محتوایی دارید که به طور منظم رفرش می شود و به طور جداگانه مدیریت می شود.

پیامدهای این تقسیم بزرگ است. در اولین بازدید می توانید محتوا را روی سرور رندر کنید و سرویس ورکر را روی کلاینت نصب کنید. در بازدیدهای بعدی فقط به درخواست داده نیاز دارید.

در مورد افزایش پیشرونده چطور؟

در حالی که سرویس‌کار در حال حاضر توسط همه مرورگرها پشتیبانی نمی‌شود، معماری پوسته محتوای برنامه از پیشرفت تدریجی استفاده می‌کند تا اطمینان حاصل شود که همه می‌توانند به محتوا دسترسی داشته باشند. به عنوان مثال، نمونه پروژه ما را در نظر بگیرید.

در زیر می توانید نسخه کامل رندر شده در کروم، فایرفاکس نایتلی و سافاری را مشاهده کنید. در سمت چپ می توانید نسخه سافاری را ببینید که در آن محتوا بدون سرویس کار بر روی سرور ارائه می شود. در سمت راست، نسخه‌های Chrome و Firefox Nightly را می‌بینیم که توسط Service Worker پشتیبانی می‌شوند.

تصویر Application Shell بارگذاری شده در Safari، Chrome و Firefox

چه زمانی استفاده از این معماری منطقی است؟

معماری پوسته اپلیکیشن برای اپلیکیشن‌ها و سایت‌هایی که پویا هستند، بیشترین معنا را دارد. اگر سایت شما کوچک و ثابت است، احتمالاً نیازی به پوسته برنامه ندارید و می‌توانید به سادگی کل سایت را در مرحله oninstall سرویس‌کار ذخیره کنید. از رویکردی استفاده کنید که بیشترین معنا را برای پروژه شما دارد. تعدادی از چارچوب های جاوا اسکریپت قبلاً جدا کردن منطق برنامه شما را از محتوا تشویق می کنند و این الگو را برای اعمال ساده تر می کند.

آیا هنوز برنامه های تولیدی با استفاده از این الگو وجود دارد؟

معماری پوسته برنامه تنها با چند تغییر در رابط کاربری کلی برنامه شما امکان پذیر است و برای سایت های مقیاس بزرگ مانند برنامه وب پیشرو I/O 2015 گوگل و صندوق ورودی گوگل به خوبی کار کرده است.

تصویر بارگیری صندوق ورودی Google. صندوق ورودی را با استفاده از Service Worker نشان می دهد.

پوسته های برنامه آفلاین یک پیروزی بزرگ در عملکرد هستند و همچنین در برنامه آفلاین ویکی پدیا جیک آرچیبالد و برنامه وب مترقی Flipkart Lite به خوبی نشان داده می شوند.

تصاویری از نسخه ی نمایشی ویکی پدیا جیک آرچیبالد.

توضیح معماری

در طول اولین تجربه بارگذاری، هدف شما این است که محتوای معنادار را در سریع ترین زمان ممکن به صفحه نمایش کاربر برسانید.

ابتدا صفحات دیگر را بارگیری و بارگذاری کنید

نمودار اولین بار با پوسته برنامه

به طور کلی معماری پوسته برنامه:

  • بار اولیه را اولویت بندی کنید، اما به سرویسکار اجازه دهید پوسته برنامه را در حافظه پنهان نگه دارد تا بازدیدهای مکرر نیازی به واکشی مجدد پوسته از شبکه نداشته باشد.

  • بار تنبل یا پس‌زمینه هر چیز دیگری را بارگیری می‌کند. یکی از گزینه های خوب استفاده از کش خواندن از طریق برای محتوای پویا است.

  • برای مثال، از ابزار service worker، مانند sw-precache ، برای ذخیره و به روز رسانی قابل اعتماد سرویس‌کار که محتوای ثابت شما را مدیریت می‌کند، استفاده کنید. (در ادامه بیشتر در مورد sw-precache.)

برای رسیدن به این هدف:

  • سرور محتوای HTML را ارسال می‌کند که مشتری می‌تواند آن را ارائه کند و از سرصفحه‌های انقضای حافظه پنهان HTTP در آینده استفاده کند تا مرورگرهایی را بدون پشتیبانی سرویس‌دهنده حساب کند. این نام فایل‌ها را با استفاده از هش‌ها ارائه می‌کند تا هم «نسخه‌سازی» و هم به‌روزرسانی‌های آسان را برای آینده در چرخه عمر برنامه فعال کند.

  • صفحه(ها) سبک های CSS درون خطی را در یک تگ <style> در سند <head> شامل می شود تا اولین رنگ سریع پوسته برنامه را ارائه دهد. هر صفحه به طور ناهمزمان جاوا اسکریپت لازم برای نمای فعلی را بارگیری می کند. از آنجایی که CSS نمی‌تواند به‌صورت ناهمزمان بارگیری شود، می‌توانیم با استفاده از جاوا اسکریپت استایل‌ها را درخواست کنیم زیرا ناهمزمان است و نه تجزیه‌کننده و همزمان. همچنین می‌توانیم از requestAnimationFrame() استفاده کنیم تا از مواردی جلوگیری کنیم که ممکن است به سرعت در حافظه پنهان ضربه بخوریم و در نهایت سبک‌ها به طور تصادفی بخشی از مسیر رندر بحرانی شوند. requestAnimationFrame() اولین فریم را مجبور می کند قبل از بارگذاری سبک ها نقاشی شود. گزینه دیگر استفاده از پروژه هایی مانند loadCSS گروه Filament برای درخواست CSS به صورت ناهمزمان با استفاده از جاوا اسکریپت است.

  • Service Worker یک ورودی ذخیره‌شده از پوسته برنامه را ذخیره می‌کند تا در بازدیدهای مکرر، پوسته کاملاً از کش سرویس‌کار بارگیری شود، مگر اینکه به‌روزرسانی در شبکه موجود باشد.

پوسته برنامه برای محتوا

یک پیاده سازی عملی

ما یک نمونه کاملاً کارآمد با استفاده از معماری پوسته برنامه، جاوا اسکریپت vanilla ES2015 برای مشتری و Express.js برای سرور نوشته‌ایم. البته هیچ چیز مانع شما از استفاده از پشته خود برای بخش های سرویس گیرنده یا سرور (به عنوان مثال PHP، Ruby، Python) نیست.

چرخه عمر کارگر خدماتی

برای پروژه پوسته برنامه خود، از sw-precache استفاده می کنیم که چرخه عمر کارگر سرویس زیر را ارائه می دهد:

رویداد عمل
نصب پوسته برنامه و دیگر منابع برنامه تک صفحه ای را کش کنید.
فعال کنید کش های قدیمی را پاک کنید.
رفتن و آوردن یک برنامه وب یک صفحه را برای URL ها ارائه دهید و از حافظه پنهان برای دارایی ها و قسمت های از پیش تعریف شده استفاده کنید. از شبکه برای درخواست های دیگر استفاده کنید.

بیت های سرور

در این معماری، یک جزء سمت سرور (در مورد ما، نوشته شده در Express) باید بتواند محتوا و ارائه را به طور جداگانه بررسی کند. محتوا را می توان به یک طرح بندی HTML اضافه کرد که منجر به رندر ایستا از صفحه می شود، یا می توان آن را به طور جداگانه و به صورت پویا بارگذاری کرد.

قابل درک است که راه اندازی سمت سرور شما ممکن است به شدت با تنظیماتی که ما برای برنامه آزمایشی خود استفاده می کنیم متفاوت باشد. این الگوی برنامه های وب با اکثر تنظیمات سرور قابل دستیابی است، اگرچه نیاز به معماری مجدد دارد . ما متوجه شدیم که مدل زیر به خوبی کار می کند:

نمودار معماری پوسته برنامه
  • نقاط پایانی برای سه بخش از برنامه شما تعریف می‌شوند: URLهای کاربر (نمایه/کارت عام)، پوسته برنامه (سرویس‌کار) و قسمت‌های HTML شما.

  • هر نقطه پایانی دارای یک کنترل‌کننده است که طرح‌بندی فرمان را می‌کشد که به نوبه خود می‌تواند قسمت‌ها و نماهای فرمان را بکشد. به بیان ساده، جزئی ها نماهایی هستند که تکه هایی از HTML هستند که در صفحه نهایی کپی می شوند. توجه: فریم‌ورک‌های جاوا اسکریپت که همگام‌سازی داده‌های پیشرفته‌تری را انجام می‌دهند، اغلب به آسانی به معماری Application Shell منتقل می‌شوند. آنها تمایل دارند از اتصال داده و همگام سازی به جای جزئی استفاده کنند.

  • در ابتدا یک صفحه ثابت با محتوا به کاربر ارائه می شود. این صفحه یک سرویس‌کار را ثبت می‌کند، در صورت پشتیبانی، که پوسته برنامه و هر چیزی که به آن بستگی دارد (CSS، JS و غیره) را در حافظه پنهان نگه می‌دارد.

  • پوسته برنامه سپس به عنوان یک برنامه وب تک صفحه ای عمل می کند و از جاوا اسکریپت به XHR در محتوا برای یک URL خاص استفاده می کند. فراخوانی های XHR به یک نقطه پایانی /partials* انجام می شود که بخش کوچکی از HTML، CSS و JS مورد نیاز برای نمایش آن محتوا را برمی گرداند. توجه: راه های زیادی برای نزدیک شدن به این موضوع وجود دارد و XHR تنها یکی از آنهاست. برخی از برنامه‌ها داده‌های خود را (شاید از JSON استفاده می‌کنند) برای رندر اولیه قرار می‌دهند و بنابراین در مفهوم HTML مسطح «ایستا» نیستند.

  • مرورگرهای بدون پشتیبانی کارگر سرویس همیشه باید یک تجربه بازگشتی داشته باشند. در نسخه ی نمایشی خود، به رندر سمت سرور استاتیک برمی گردیم، اما این تنها یکی از گزینه های متعدد است. جنبه سرویس کار فرصت های جدیدی را برای افزایش عملکرد برنامه سبک برنامه تک صفحه ای خود با استفاده از پوسته برنامه ذخیره شده در حافظه پنهان در اختیار شما قرار می دهد.

نسخه سازی فایل

یک سوال که مطرح می شود این است که چگونه می توان نسخه و به روز رسانی فایل را مدیریت کرد. این مخصوص برنامه است و گزینه ها عبارتند از:

  • ابتدا شبکه کنید و در غیر این صورت از نسخه کش استفاده کنید.

  • فقط شبکه و در صورت آفلاین خراب می شود.

  • نسخه قدیمی را کش و بعداً به روز کنید.

برای خود پوسته برنامه، باید یک رویکرد اول حافظه پنهان برای راه‌اندازی سرویس‌کار شما در نظر گرفته شود. اگر پوسته برنامه را کش نمی‌کنید، معماری را به درستی قبول نکرده‌اید.

ابزار سازی

ما تعدادی از کتابخانه های کمکی سرویس کارمند مختلف را نگهداری می کنیم که فرآیند پیش کش کردن پوسته برنامه شما یا مدیریت الگوهای ذخیره سازی رایج را برای راه اندازی آسان تر می کند.

تصویری از سایت کتابخانه Service Worker در Web Fundamentals

از sw-precache برای پوسته برنامه خود استفاده کنید

استفاده از sw-precache برای کش کردن پوسته برنامه باید نگرانی‌های مربوط به ویرایش فایل، سوالات نصب/فعال‌سازی و سناریوی واکشی پوسته برنامه را برطرف کند. sw-precache را در فرآیند ساخت برنامه خود رها کنید و از حروف عام قابل تنظیم برای انتخاب منابع استاتیک خود استفاده کنید. به جای ساخت دستی اسکریپت Service Worker خود، اجازه دهید sw-precache اسکریپتی ایجاد کند که حافظه پنهان شما را به صورت ایمن و کارآمد با استفاده از یک کنترل کننده واکشی cache-first مدیریت کند.

بازدیدهای اولیه از برنامه شما باعث پیش کش کردن مجموعه کامل منابع مورد نیاز می شود. این شبیه به تجربه نصب یک برنامه بومی از یک فروشگاه برنامه است. وقتی کاربران به برنامه شما باز می گردند، فقط منابع به روز دانلود می شوند. در نسخه ی نمایشی خود، هنگامی که پوسته جدیدی در دسترس است، با پیام «به روز رسانی برنامه. برای نسخه جدید بازخوانی کنید» به کاربران اطلاع می دهیم. این الگو راهی کم اصطکاک است که به کاربران اطلاع می دهد می توانند آخرین نسخه را به روز کنند.

از sw-toolbox برای کش در زمان اجرا استفاده کنید

از sw-toolbox برای کش کردن زمان اجرا با استراتژی های متفاوت بسته به منبع استفاده کنید:

  • cacheFirst برای تصاویر، به همراه یک کش اختصاصی با نام که دارای خط مشی انقضای سفارشی N maxEntries است.

  • شبکه اول یا سریعترین برای درخواستهای API، بسته به تازگی محتوای مورد نظر. Fasttest ممکن است خوب باشد، اما اگر فید API خاصی وجود دارد که مرتباً به روز می شود، از networkFirst استفاده کنید.

نتیجه

معماری پوسته برنامه دارای چندین مزیت است، اما فقط برای برخی از کلاس‌های کاربردی منطقی است. این مدل هنوز جوان است و ارزش ارزیابی تلاش و مزایای عملکرد کلی این معماری را دارد.

در آزمایش‌های خود، از اشتراک‌گذاری قالب بین مشتری و سرور برای به حداقل رساندن کار ساخت دو لایه برنامه استفاده کردیم. این تضمین می‌کند که بهبود تدریجی همچنان یک ویژگی اصلی است.

اگر از قبل در نظر دارید از سرویس‌دهنده‌ها در برنامه خود استفاده کنید، نگاهی به معماری بیندازید و ارزیابی کنید که آیا برای پروژه‌های شما منطقی است یا خیر.

با تشکر از منتقدان ما: جف پوسنیک، پل لوئیس، الکس راسل، ست تامپسون، راب دادسون، تیلور ساویج و جو مدلی.