عاملو الخدمة ونموذج هيكل التطبيق

إحدى الميزات المعمارية الشائعة لتطبيقات الويب ذات الصفحة الواحدة (SPA) هي الحد الأدنى من مجموعة HTML وCSS وJavaScript المطلوبة لتفعيل الوظائف العامة للتطبيق. من الناحية العملية، غالبًا ما يكون هذا هو العنوان والتنقل وغيرها من عناصر واجهة المستخدم الشائعة التي تظل موجودة عبر جميع الصفحات. عندما يخزّن عامل الخدمة محتوى HTML البسيط لواجهة المستخدم هذه ومواد العرض التابعة مؤقتًا في ذاكرة التخزين المؤقت، نُطلق على هذا اسم هيكل التطبيق.

رسم تخطيطي لهيكل تطبيق. وهي لقطة شاشة لصفحة ويب مع عنوان في الأعلى ومنطقة محتوى في الأسفل. يكون العنوان باسم "Application Shell"، بينما يتم تصنيف الجزء السفلي على أنه "المحتوى".

يلعب هيكل التطبيق دورًا مهمًا في الأداء الملحوظ لتطبيق الويب. إنه أول شيء يتم تحميله، وبالتالي فهو أيضًا أول شيء يراه المستخدمون أثناء انتظار تعبئة المحتوى لواجهة المستخدم.

على الرغم من سرعة تحميل هيكل التطبيق، بشرط أن تكون الشبكة متاحة وسريعة إلى حد ما، إلا أنّ عامل الخدمة الذي يخزّن هيكل التطبيق والأصول المرتبطة به مؤقتًا يمنح نموذج هيكل التطبيق المزايا الإضافية التالية:

  • أداء موثوق ومتسق في الزيارات المتكررة: في الزيارة الأولى لتطبيق بدون تثبيت مشغّل الخدمات، يجب تحميل ترميز التطبيق والأصول المرتبطة به من الشبكة قبل أن يتمكن عامل الخدمة من وضعها في ذاكرة التخزين المؤقت. ومع ذلك، ستؤدي الزيارات المتكررة إلى سحب هيكل التطبيق من ذاكرة التخزين المؤقت، مما يعني أن التحميل والعرض سيكونان فوريين.
  • الوصول الموثوق إلى الوظائف في سيناريوهات عدم الاتصال بالإنترنت: في بعض الأحيان يكون الوصول إلى الإنترنت متقطعًا أو غير موجود تمامًا، وقد يتعذر علينا العثور على هذا الموقع والشاشة مقفلة. يعالج نموذج هيكل التطبيق هذا من خلال الاستجابة لأي طلب تنقل بترميز هيكل التطبيق من ذاكرة التخزين المؤقت. وحتى إذا زار شخص عنوان URL في تطبيق الويب لم يزوره من قبل، سيتم عرض هيكل التطبيق من ذاكرة التخزين المؤقت، ويمكن ملؤه بمحتوى مفيد.

متى يجب استخدام نموذج هيكل التطبيق

يكون هيكل التطبيق أكثر منطقية عندما يكون لديك عناصر واجهة مستخدم شائعة لا تتغير من مسار إلى آخر، ولكن يتغير المحتوى. تستخدم معظم SPA على الأرجح ما يمثل نموذجًا فعالاً لهيكل التطبيق.

إذا كان هذا يصف مشروعك، وأردت إضافة عامل خدمات لتحسين موثوقيته وأدائه، فإن هيكل التطبيق يجب أن:

  • سرعة التحميل:
  • استخدام مواد العرض الثابتة من مثيل Cache
  • تضمين عناصر الواجهة الشائعة، مثل العنوان والشريط الجانبي، بشكل منفصل عن محتوى الصفحة.
  • استرداد المحتوى الخاص بالصفحة وعرضه
  • إذا كان ذلك مناسبًا، يمكنك تخزين المحتوى الديناميكي مؤقتًا وعرضه بلا اتصال بالإنترنت.

يُحمِّل هيكل التطبيق محتوى خاصًا بالصفحة ديناميكيًا من خلال واجهات برمجة التطبيقات أو المحتوى المجمّع في JavaScript. ويجب أيضًا أن يتم تحديثه ذاتيًا بحيث يعني أنه إذا تغير ترميز هيكل التطبيق، فإن تحديث عامل الخدمة يجب أن يلتقط هيكل التطبيق الجديد ويخزّنه في ذاكرة التخزين المؤقت تلقائيًا.

إنشاء هيكل التطبيق

يجب أن يتوفّر هيكل التطبيق بشكل مستقل عن المحتوى، ولكن يجب توفير قاعدة تتم تعبئتها داخل المحتوى. ومن المفترض أن يكون خفيفًا قدر الإمكان، ولكن يتضمّن قدرًا كافيًا من المحتوى المفيد في عملية التنزيل الأوّلية حتى يعرف المستخدم أنّ التجربة يتم تحميلها بسرعة.

يعتمد التوازن المناسب على تطبيقك. تشتمل هيكل التطبيق الخاص بتطبيق التدريب على الإثارة من جيك أرشيبالد على عنوان به زر تحديث لسحب محتوى جديد من Flickr.

لقطة شاشة لتطبيق الويب "تدريب على الإثارة" في ولايتين مختلفتين. على يمين الشاشة، لن يظهر سوى هيكل التطبيق المخزّن مؤقتًا بدون تعبئة أي محتوى. على يسار الشاشة، يتم تحميل المحتوى (بضع صور لبعض القطارات) ديناميكيًا في منطقة محتوى هيكل التطبيق.

سيختلف ترميز هيكل التطبيق من مشروع إلى آخر، ولكن في ما يلي مثال على ملف index.html يعرض النص النموذجي للتطبيق:

​​<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      Application Shell Example
    </title>
    <link rel="manifest" href="/manifest.json">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <link rel="stylesheet" type="text/css" href="styles/global.css">
  </head>
  <body>
    <header class="header">
      <!-- Application header -->
      <h1 class="header__title">Application Shell Example</h1>
    </header>

    <nav class="nav">
      <!-- Navigation items -->
    </nav>

    <main id="app">
      <!-- Where the application content populates -->
    </main>

    <div class="loader">
      <!-- Spinner/content placeholders -->
    </div>

    <!-- Critical application shell logic -->
    <script src="app.js"></script>

    <!-- Service worker registration script -->
    <script>
      if ('serviceWorker' in navigator) {
        // Register a service worker after the load event
        window.addEventListener('load', () => {
          navigator.serviceWorker.register('/sw.js');
        });
      }
    </script>
  </body>
</html>

ومع ذلك، عند إنشاء هيكل تطبيق لمشروعك، يجب أن يتميز بالخصائص التالية:

  • يجب أن يحتوي HTML على مناطق معزولة بوضوح لعناصر واجهة المستخدم الفردية. في المثال أعلاه، يتضمن ذلك عنوان التطبيق والتنقل ومنطقة المحتوى الرئيسية ومساحة مؤشر التحميل تظهر فقط عند تحميل المحتوى
  • يجب أن يكون حجما جافا سكريبت وCSS الأولية اللذين تم تحميلهما لهيكل التطبيق بسيطين، وأن يكونا مرتبطين فقط بوظيفة هيكل التطبيق نفسه وليس بالمحتوى. ويضمن هذا أن يعرض التطبيق هيكله بأسرع وقت ممكن، كما يصغر سلسلة العمل الرئيسية إلى أن يظهر المحتوى.
  • يشير ذلك المصطلح إلى نص برمجي مضمّن يسجّل مشغّل الخدمات.

بعد إنشاء هيكل التطبيق، يمكنك إنشاء عامل خدمة لتخزينه وأصوله في ذاكرة التخزين المؤقت.

التخزين المؤقت لهيكل التطبيق

يجب أن يخزّن عامل الخدمة هيكل التطبيق وأصوله المطلوبة في ذاكرة التخزين المؤقت على الفور عند التثبيت. بافتراض وجود هيكل تطبيق مثل المثال أعلاه، لنتعرف على كيفية تحقيق ذلك في مثال أساسي لمربع العمل باستخدام workbox-build:

// build-sw.js
import {generateSW} from 'workbox-build';

// Where the generated service worker will be written to:
const swDest = './dist/sw.js';

generateSW({
  swDest,
  globDirectory: './dist',
  globPatterns: [
    // The necessary CSS and JS for the app shell
    '**/*.js',
    '**/*.css',
    // The app shell itself
    'shell.html'
  ],
  // All navigations for URLs not precached will use this HTML
  navigateFallback: 'shell.html'
}).then(({count, size}) => {
  console.log(`Generated ${swDest}, which precaches ${count} assets totaling ${size} bytes.`);
});

تعمل هذه الإعدادات المخزَّنة في build-sw.js على استيراد CSS وJavaScript الخاصة بالتطبيق، بما في ذلك ملف ترميز هيكل التطبيق المُضمَّن في shell.html. يتم تنفيذ النص البرمجي باستخدام Node على النحو التالي:

node build-sw.js

تتم كتابة مشغّل الخدمات الذي تم إنشاؤه إلى ./dist/sw.js، وسيسجّل الرسالة التالية عند الانتهاء:

Generated ./dist/sw.js, which precaches 5 assets totaling 44375 bytes.

عند تحميل الصفحة، يخزّن عامل الخدمة ترميز هيكل التطبيق وتبعياته مؤقتًا:

لقطة شاشة للوحة الشبكة في &quot;أدوات مطوري البرامج&quot; في Chrome تعرض قائمة بأصول تم تنزيلها من الشبكة. تتميّز مواد العرض التي يخزّنها مشغّل الخدمات مؤقتًا عن مواد العرض الأخرى التي يظهر بجانبها رمز الترس على يمين الصف. يخزن عامل الخدمة مؤقتًا العديد من ملفات JavaScript وCSS بشكل مسبق أثناء التثبيت.
يخزّن عامل الخدمة تبعيات هيكل التطبيق في ذاكرة التخزين المؤقت أثناء التثبيت. تشير طلبات التخزين المؤقت إلى آخر صفَّين، ويشير رمز الترس بجانب الطلب إلى أنّ عامل الخدمة قد تعامل مع الطلب.

يمكن إعداد HTML وCSS وJavaScript مسبقًا في أي سير عمل تقريبًا، بما في ذلك المشاريع التي تستخدم برامج التجميع. أثناء تقدّمك في المستندات، ستتعلّم كيفية استخدام Workbox مباشرةً لإعداد سلسلة الأدوات الخاصة بك لإنشاء مشغّل خدمات يناسب مشروعك، بغض النظر عمّا إذا كان SPA.

الخاتمة

إنّ الجمع بين نموذج هيكل التطبيق ومشغّل الخدمات أمرٌ رائعٌ للتخزين المؤقت بلا اتصال بالإنترنت، لا سيما إذا كنت تجمع بين وظيفة التخزين المؤقت واستراتيجية الشبكة أولاً والعودة إلى ذاكرة التخزين المؤقت للترميز أو لاستجابات واجهة برمجة التطبيقات. والنتيجة هي تجربة سريعة موثوق بها ستعرض هيكل تطبيقك على الفور عند تكرار الزيارات، حتى في ظروف عدم الاتصال بالإنترنت.