دسته بندی: 

Shikhar Kapoor از Flipkart، شما را در چگونگی ساخت یک اپلیکیشن وب با کمک Service Workers و app shells راهنمایی می‌کند.

اپلیکیشن‌های محلی موبایل، از طریق فراهم نمودن یک تجربه‌ی غنی و قابل اطمینان اینترنتی، رکورد قابل توجهی برای وب بر جای گذاشته‌اند. هرچند، از منظر قابل کشف بودن، وب به یک نمونه‌ی پیش‌رو و غیر قابل شکست در یک دهه‌ی اخیر تبدیل شده است. با توجه یه این که وندورهای مرورگر بیش از پیش هدف خود برای پل زدن برروی این فاصله را نشان می‌دهند نبرد "غنی در برابر قابل دسترس" نهایتا در حال کاهش است. (Progressive web apps(PWAs، مفهومی که از نیاز به کم کردن محدودیت‌های وب متولد شد، جبهه‌‌ای را باز کرده که توسعه‌دهنده‌ها می‌توانند از مزایای هر دو دنیا بهره‌مند شوند. براساس اعلام گوگل، یک PWA از مشخصات زیر برخوردار است:

  • بارگزاری سریع: به منظور بارگزاری اپلیکیشن‌های شما کاربران نباید بیش از حد منتظر بمانند. دُرُست مثل اپلیکیشن‌های محلی، آن‌ها به محض این که یک اپلیکیشن را باز می‌کنند باید اطلاعات مرتبط با آن را مشاهده نمایند.
  • ایمن: محتوای کاربر ایمن است و اپلیکیشن نمی‌تواند آن را تغییر دهد.
  • شبیه App: آن‌ها رفتار‌هایی مثل پشتیبانی از push notifications را اموله می‌کنند و باید بتوانند به خوبی از سنسورهای دیوایس استفاده کرده و آن را توسعه دهند.  
  • قابل کشف و قابل لینک دادن: PWAها توسط موتورهای جست‌و‌جو قابل جست‌و‌جو هستند و نیازی به بازار خاصی در این خصوص ندارند. به واسطه‌ی روشی که وب بر آن اساس بنا شده است، ما به این ویژگی دست پیدا می‌کنیم.
  • پیش‌رونده: این اپلیکیشن‌ها براساس بهینه‌سازی‌های پیش‌رونده به عنوان یک اصل کلیدی بنا شده‌اند.
  • قابل نصب: کاربران می‌توانند بدون طی کردن روال‌های پیچیده‌ی نصب، PWAها را برروی دیوایس‌های خود نصب کنند. ویژگی‌هایی نظیر پشتیبانی از Add to homescreen و splash screen، این اپلیکیشن‌ها را قابل نصب می‌کنند و تجربه‌ی کاربری یکپارچه‌ای فراهم می‌نمایند، دُرُست مثل هر اپلیکیشن محلی دیگر.

اپلیکیشن دمو

بیایید اپلیکیشن خودمان را براساس ایده‌‌هایی که در بالا لیست کردیم بسازیم. ما یک PWA بسیار ساده که تمام پُست‌های صفحه‌ی اصلی Reddit را نمایش می‌دهد با استفاده از API عمومی Reddit ایجاد می‌کنیم. این اپلیکیشن، مثل هر اپلیکیشن وب پیش‌رونده‌ی دیگر، باید برروی همه‌ی شبکه‌ها اجرا شود، باید قابل نصب باشد و باید به شکل یک اپلیکیشن مستقل نیز اجرا شود. در عین حال باید سریعا بارگزاری شود. برای این که هدف ما را درک کنید نگاهی به دموی موجود در netm.ag/demo-286 بیندازید.

ساختار اپلیکیشن

برای اولین درخواست، ما یک فراخوانی شبکه انجام می‌دهیم و پاسخ را در کَش ذخیره می‌کنیم (در این مورد، app shell). برای درخواست‌های بعدی، ما app shell خود را به شکل یک محتوای کَش شده در می‌آوریم. Service Worker مثل یک پروکسی بین اپلیکیشن ما و سرور عمل می‌کند و هر بار که یک منبع را درخواست می‌کنیم آن را رفرش می‌نمائیم. Application shells،کانتینرهایی برای اپلیکیشن وب شما هستند. این shellها:

  • باید از حداقل HTML, CSS و JavaScript مورد نیاز برای رندر محتوای استاتیک، در کنار bootstrap code اپلیکیشن شما برخوردار باشند.
  • یک وضعیت بارگزاری از اپلیکیشن شما تعریف نمایند.
  • باید سریع بارگزاری شده و کَش شوند.

بیایید یک basic shell برای اپلیکیشن خود ایجاد کنیم. ما ابتدا درباره‌ی وضعیت بارگزاری تصمیم‌گیری می‌کنیم. برای پُست‌های Reddit خود، در حالی که پُست‌های ما fetch می‌شوند، placeholderهایی ایجاد می‌نمائیم:

 از این نقطه، ما فقط باید یک سرور سُبک ایجاد کنیم (به عنوان مثال با استفاده از Express) تا بتوانیم فایل‌های خود را به شکل محلی ارائه نمائیم.

Service Worker

برای این که اپلیکیشن‌های  وب خود را به طور واقعی پیشرونده سازیم، نیاز داریم که همه‌ی آن‌ها در هر شرایطی بار شوند و زمانی که شبکه در دسترس نیست یک اسکرین آف‌لاین را به کاربر نشان ندهند. به واسطه‌ی وجود Service Workers، ما حالا می‌توانیم چگونگی کارکرد اپلیکیشن‌های‌مان را در مواقعی که شبکه ضعیف است کنترل نمائیم. Service Workers، اسکریپت‌های workerی هستند که در پس‌زمینه اجرا می‌شوند و می‌توانند به فراخوانی‌های شبکه که اپلیکیشن‌ها انجام می‌دهند گوش فرا دهند یا با آن تعامل کنند. قبل از این که کارمان شروع کنیم، یک فایل sw.js ایجاد کنید و آن را خالی بگذارید-ما دوباره به این‌جا برمی‌گردیم و منطق کَشینگ خود را در این فایل می‌نویسیم. حالا بیائید این اسنیپت Service Worker را به app shell خود اضافه نمائیم:

این اسکریپت چک می‌کند که آیا Service Worker توسط مرورگر پشتیبانی می‌شود یا نه و سپس فایل Service Workersی که به تابع register عبور می‌دهید (در این‌جا ‎/sw.js) رجیستر می‌نماید. در این‌جا چند نکته وجود دارد که باید به آن‌ها توجه کنیم. اول، Service Workers رجیستر شده باید فقط از طریق HTTPS ارائه شود. هرچند، localhost برای اهداف توسعه در لیست سفید قرار می‌گیرد. دوم، Service Worker همیشه باید از همان منبع اصلی اپلیکیشن وب شما ارائه شود.

اضافه کردن Manifest

ما حالا برروی قابل نصب کردن اپلیکیشن وب خود کار می‌کنیم. برای این کار، ما به آیکون‌هایی برای اپلیکیشن خود و فایلی به اسم manifest.json نیاز داریم. این فایل، پیکره‌بندی مرکزی شده‌ی اپلیکیشن و فوق‌داده (metadata) را در خود نگه می‌دارد. User-agents از این فایل برای یادآوری این نکته که اپلیکیشن شما مثل یک اپلیکیشن وب قابل نصب است استفاده می‌کنند. در JSON config شما می‌توانید موارد زیر را تعریف کنید:

  • اسم اپلیکیشن: برای نمایش اسم اپلیکیشن شما در زیر آیکونی که در صفحه‌ی خانگی قرار دارد استفاده می‌شود.
  • حالت نمایش (Display mode): این، چگونگی عرضه شدن اپلیکیشن شما به کاربران را کنترل می‌کند. Display mode می‌تواند یکی از مقادیر fullscreen, standalone, minimal-ui یا browser را داشته باشد.
  • آیکون‌ها: این‌ها اپلیکیشن شما را برروی splash screen و آیکون صفحه‌ی خانگی ارائه می‌کنند. آخری به شکل پیش‌فرض انتخاب می‌شود، minimal-ui دومی است و این روند تا fullscreen دنبال می‌شود.
  • جهت (Orientation): شما می‌توانید جهت اپلیکیشن خود را انتخاب کنید: portrait یا landscape.
  • URL آغازین: URLی که می‌خواهید وقتی کاربر اپلیکیشن شما را اجرا می‌کند ظاهر شود است.
  • رنگ تِم: این، رنگ تم پیش‌فرض را ست می‌کند و در عین حال رنگ نوار وضعیت را در اندروید تغییر می‌دهد.
  • رنگ پس‌زمینه: رنگ پس‌زمینه‌ی اپلیکیشن شما را قبل از این که static assets، رنگ پس‌زمینه‌ای که قبلا بارگزاری کرده‌اید تعریف کند ست می‌کند.

به منظور رجیستر کردن فایل manifest.json اپلیکیشن خود، یک فایل با همین اسم را در پوشه‌ی ریشه‌ بیندازید و برچسب زیر را به shell اپلیکیشن اضافه کنید:

سپس، یک manifest.json در دایرکتوری ریشه ایجاد و پیکره‌بندی زیرا را اضافه نمائید:

کارکرد در حالت آف‌لاین:

حال که اپلیکیشن وب خود را قابل نصب کردیم، بیایید کاری کنیم تا با استفاده از برخی از جنبه‌های جادویی Service Worker، به شکل آف‌لاین یا برروی شبکه‌های کُند نیز جواب دهد. اما قبل از این که شروع به نوشتن کُد Service Worker برای اپلیکیشن خود کنید، بیایید درباره‌ی استراتژی caching تصمیم‌گیری نمائیم. چندین استراتژی برای cache کردن داده‌ها با استفاده از Service Workers وجود دارد. برخی از آن‌ها به شرح زیر هستند:

  • Network-first (اول شبکه): همیشه تلاش کنید ابتدا داده‌ها را از منبع اصلی بگیرید و اگر شبکه از کار افتاد به کَش برگردید. وقتی فراخوانی شبکه با موفقیت انجام بگیرد، شما cache را آپ‌دیت می‌کنید و بدین ترتیب مقداری داده دارید که وقتی دسترسی به شبکه وجود ندارد به کاربران ارائه می‌کنید. این روش در مواقعی که همیشه نیاز به نمایش داده‌های دینامیک (مثل قیمت، ارزش سهام و غیره) دارید روش ارجح محسوب می‌شود.
  • Cache-first (اول کَش): این استراتژی با روش offline-first در ساخت اپلیکیشن‌ها عالی کار می‌کند. شما ابتدا تلاش می‌کنید داده‌ها را از کَش fetch کنید و اگر داده‌ها در کَش وجود نداشتند بعدا به شبکه برگردید. شما در عین حال یک فراخوانی شبکه را برای آپ‌دیت کردن کَش برای موفقیت بعدی اجرا می‌نمائید.
  • سریع‌ترین: درخواست‌ها را از شبکه و کَش به طور موازی درخواست کنید اما فقط سریع‌ترین پاسخ برگشتی را منظور کنید.
  • فقط cache: همیشه از کَش fetch کنید. اگر داده‌ها در کَش قرار ندارند ابتدا cache را آپ‌دیت کنید و سپس داده‌ها را فراهم نمائید.
  • فقط شبکه: بدون caching، همیشه از شبکه fetch کنید.

کارکرد اپلیکیشن ما در زمانی که آف‌لاین است اهمیت دارد و اگر داده‌های کهنه و قدیمی را برای دمو به کاربر نشان دهیم اهمیتی ندارد بنابراین ما استراتژی "اول کَش" را انتخاب می‌کنیم. بهتر است مدتی را صَرف تصمیم‌گیری درباره‌ی بهترین استراتژی کَش برای اپلیکیشن خود کنید زیرا تاثیر وسیعی بر تجربه‌ای که قرار است برای کاربران خود فراهم نمائید دارد. علاوه بر این، اگر اطلاعاتی که ارائه می‌کنید برای کاربر حیاتی و فرار باشند (مثل قیمت‌ها یا امتیازها) ارائه‌ی داده‌های قدیمی می‌توانند شما را با دردسر مواجه سازند. بیایید برای cache کردن منابع از طریق Service Workers و Cache API کُد لازم را بنویسیم. درون sw.js، به منظور ایجاد یک کَش جدید در caching API مرورگر اسنیپت زیر و منابعی که باید cache شوند اضافه کنید:

توصیه می‌شود cache خود را نسخه‌بندی کنید. در زمانی که می‌خواهید مجموعه‌ی جدیدی از منابع cache شوند و درنتیجه موضوع پاک‌سازی آن به میان می‌آید این کار به شما کمک خواهد کرد. سپس، ما منطق گوش کردن به رویداد fetch را به مرورگر اضافه می‌کنیم و برای فراهم نمودن داده‌ها از cache (اگر در دسترس قرار داشته باشد)، فراخوانی‌های شبکه را قطع و در آن دخالت می‌کنیم. در عین حال، برای آپ‌دیت کردن cache با داده‌های تازه، یک فراخوان شبکه اجرا می‌نمائیم:

نوتیفیکیشن آف‌لاین

اگر به کاربر اجازه دهیم وقتی آف‌لاین است از همه چیز اطلاع داشته باشد همیشه ایده‌ی خوبی است. برای نمایش نوتیفیکیشن آف‌لاین، یک عنصر پنهان در app shell ایجاد کرده و اسکریپت زیر را دُرُست قبل از برچسب closing body اضافه کنید:

   

اجرای مثال

وقتی شما اپلیکیشن را برای اولین بار در مرورگر خود اجرا می‌کنید، وضعیت بارگزاری تعریف شده در shell اپلیکیشن را مشاهده خواهید کرد و زمانی که داده‌ها در نهایت fetch می‌شوند شما وضعیت رندر کامل اپلیکیشن را می‌بینید. اگر شبکه را غیرفعال کنید، باید یک نوار (شبیه نواری که در عکس 6 می‌بینید ) مشاهده کنید که به شما می‌گوید در حال مرور اپلیکیشن به صورت آف‌لاین هستید و اگر صفحه را از نو بارگزاری کنید باید بتوانید محتوایی که آخرین دفعه بارگزاری شده بود مشاهده کنید. این بدان معنا است که اپلیکیشن شما حالا آف‌لاین کار می‌کند!. الان زمان خوبی برای چک کردن timeline در برگه‌ی Network در Chrome DevTools است. شما مشاهده می‌کنید که منابع از Service Worker برای فراخوانی‌های بعد از اولین بارگزاری fetch می‌شوند.

نتیجه‌گیری

ما فقط PWA ابتدایی خود را ایجاد کردیم اما برای این که اپلیکیشن‌های وب خود را بیش‌تر و بیش‌تر تعاملی کنید راه‌های بسیار زیاد دیگری هم وجود دارد. من شما را ترغیب می‌کنم APIهای جدید برای مرورگرها مثل Push Notification را بررسی کنید و مرزها و محدودیت‌هایی که وب به شکل سنتی تحمیل می‌کند بشکنید. PWAها، نقطه‌ی عطف جدیدی در تاریخ وب محسوب می‌شوند. وب درنهایت کار دُرُستی انجام داده است!.

توصیه‌های مهم

در این‌جا به چند موضوع کلیدی که هنگام ایجاد اپلیکیشن‌های وب پیش‌رونده باید در نظر بگیرید اشاره می‌کنیم:

  1. از یک کانشکن HTTPS استفاده کنید: Service Workers فقط با HTTPS کار می‌کند. اگرچه localhost هم whitelist است، لطفا اطمینان حاصل کنید که کُد نهایی را از طریق یک کانکشن HTTPS ارائه می‌نمائید.
  2. یک kill switch اضافه کنید: همیشه برای Service Worker خود یک kill switch اضافه نمائید. اگرچه Caching یک ابزار قدرتمند است می‌تواند غلط کار کند. لطفا مطمئن شوید هر بار که قصد دارید cache قدیمی پاک شود یک نسخه‌ی جدید در اسم cache خود اِعمال می‌کنید.
  3. از CDNها پرهیز نمائید: اطمینان حاصل کنید فایل Service Worker خود را به جای یک CDN از طریق یک سرور ارائه می‌کنید. این کار به شما اطمینان می‌دهد که همیشه نسخه‌ی تازه‌ای از فایل ارائه می‌کنید.
  4. از GET استفاده کنید: مشخصات Cache API فقط امکان کَش کردن منابع GET را فراهم می‌کند. منابعی که از طریق سایر روش‌های HTTP، fetch می‌شوند کَش نخواهند شد.
  5. App shells خود را سبک نگه دارید: باید از حداقل HTML, CSS و JavaScript در app shell خود استفاده کنید-لبریز کردن application shell می‌تواند موجب تاخیر در رندر شود که باعث ایجاد یک تجربه‌ی کاربری بد می‌گردد.
  6. پشتیبانی از Service Worker را چک کنید: در حال حاضر همه‌ی مرورگرها از  Service Workers پشتیبانی نمی‌کنند. Jake Archibald یک صفحه ایجاد کرده تا بتوانید وضعیت پشتیبانی از service workers برروی مرورگرهای مختلف را چک کنید: jakearchibald.github.io/isserviceworkerready.
 

لینک‌های مفید

در این‌جا لیستی از منابعی با اطلاعاتی درباره‌ی برخی از عناوینی که در این مقاله تحت پوشش قرار دادیم ارائه می‌کنیم. قبل از این که وارد جهان ایجاد اپلیکیشن‌های پیش‌رونده‌ی وب شوید درک عمیق این عناوین قویا توصیه می‌شود:

  1. Service Worker API‪(netm.ag/swapi)‬: یک نگاه عمیق به مفاهیم Service Worker و رفرنس‌های API. شما از این‌جا می‌توانید چیزهای بیش‌تری درباره‌ی استفاده‌های کاربردی جدید برای Service Workers مطالعه کنید.
  2. Cache‪(netm.ag/cache286)‬: درباره‌ی Cache API مرورگر اطلاعات بیش‌تری کسب کنید. این صفحه در عین حال شامل کُد اسنیپت‌هایی است که می‌توانید از آن‌ها برای شروع کار خود بهره بگیرید.
  3. The offline cookbook(netm.ag/cookbook-286): The Offline Cookbook از Jake Archibald مکانی عالی برای یادگیری درباره‌ی استراتژی‌های caching برای اپلیکیشن‌های وب پیش‌رونده به شمار می‌رود.
  4. Progressive Web App Summit talks(netm.ag/summit-286): PWA summit که گوگل میزبانی آن را به عهده دارد با متخصصان Progressive Web Apps صحبت می‌کند.

 

افزودن دیدگاه جدید