معماری اپلیکیشن‌های وب پیش‌رونده: الگوهای سرویس ورکر جاوااسکریپت | MLOG | MLOG

۴. فقط شبکه (Network-Only)

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

مثال:

            
self.addEventListener('fetch', event => {
  event.respondWith(
    fetch(event.request)
  );
});

            

۵. کهنه-ضمن-اعتبارسنجی-مجدد (Stale-While-Revalidate)

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

مثال:

            
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        const fetchPromise = fetch(event.request).then(networkResponse => {
          caches.open('my-cache').then(cache => {
            cache.put(event.request, networkResponse.clone());
            return networkResponse;
          });
        });
        return response || fetchPromise;
      })
  );
});

            

۶. کش، سپس شبکه (Cache, then Network)

شبیه به کهنه-ضمن-اعتبارسنجی-مجدد اما بدون بازگشت فوری دارایی کش شده. ابتدا کش را بررسی می‌کند و تنها در صورتی که دارایی موجود باشد، درخواست شبکه در پس‌زمینه برای به‌روزرسانی کش ادامه می‌یابد.

انتخاب استراتژی کشینگ مناسب

استراتژی کشینگ بهینه به نیازمندی‌های خاص اپلیکیشن شما بستگی دارد. عواملی مانند موارد زیر را در نظر بگیرید:

با انتخاب دقیق استراتژی‌های کشینگ مناسب، می‌توانید عملکرد و تجربه کاربری PWA خود را به طور قابل توجهی بهبود بخشید، حتی در محیط‌های آفلاین. ابزارهایی مانند Workbox ([https://developers.google.com/web/tools/workbox](https://developers.google.com/web/tools/workbox)) می‌توانند پیاده‌سازی این استراتژی‌ها را ساده کنند.

همگام‌سازی پس‌زمینه: مدیریت تغییرات در حالت آفلاین

همگام‌سازی پس‌زمینه به PWA شما اجازه می‌دهد تا وظایف را در پس‌زمینه انجام دهد، حتی زمانی که کاربر آفلاین است. این قابلیت به ویژه برای مدیریت ارسال فرم‌ها، به‌روزرسانی داده‌ها و سایر عملیاتی که به اتصال شبکه نیاز دارند، مفید است. API `BackgroundSyncManager` به شما امکان می‌دهد وظایفی را ثبت کنید که با در دسترس قرار گرفتن شبکه اجرا خواهند شد.

ثبت یک وظیفه همگام‌سازی پس‌زمینه

برای ثبت یک وظیفه همگام‌سازی پس‌زمینه، باید از متد `register` در `BackgroundSyncManager` استفاده کنید. این متد یک نام تگ منحصر به فرد را به عنوان آرگومان می‌گیرد. نام تگ، وظیفه خاصی را که باید انجام شود، مشخص می‌کند.

مثال:

            
self.addEventListener('sync', event => {
  if (event.tag === 'my-sync-task') {
    event.waitUntil(doSomeWork());
  }
});

            

مدیریت رویداد همگام‌سازی (sync)

هنگامی که مرورگر اتصال شبکه را تشخیص می‌دهد، یک رویداد `sync` را به سرویس ورکر ارسال می‌کند. شما می‌توانید به این رویداد گوش دهید و اقدامات لازم را انجام دهید، مانند ارسال داده‌ها به سرور.

مثال:

            
async function doSomeWork() {
  // Retrieve data from IndexedDB
  const data = await getDataFromIndexedDB();

  // Send data to the server
  try {
    const response = await fetch('/api/sync', {
      method: 'POST',
      body: JSON.stringify(data),
      headers: {
        'Content-Type': 'application/json'
      }
    });

    if (response.ok) {
      // Clear the data from IndexedDB
      await clearDataFromIndexedDB();
    } else {
      // Handle errors
      console.error('Sync failed:', response.status);
      throw new Error('Sync failed');
    }
  } catch (error) {
    // Handle network errors
    console.error('Network error:', error);
    throw error;
  }
}

            

مثال: ارسال فرم در حالت آفلاین

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

  1. کاربر فرم را پر کرده و در حالت آفلاین روی دکمه ارسال کلیک می‌کند.
  2. داده‌های فرم در IndexedDB ذخیره می‌شود.
  3. یک وظیفه همگام‌سازی پس‌زمینه با یک تگ منحصر به فرد (مثلاً `form-submission`) ثبت می‌شود.
  4. هنگامی که شبکه در دسترس است، رویداد `sync` فعال می‌شود.
  5. سرویس ورکر داده‌های فرم را از IndexedDB بازیابی کرده و آن را به سرور ارسال می‌کند.
  6. اگر ارسال موفقیت‌آمیز باشد، داده‌های فرم از IndexedDB حذف می‌شود.

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

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

اشتراک در پوش نوتیفیکیشن‌ها

برای دریافت پوش نوتیفیکیشن‌ها، کاربران باید ابتدا به PWA شما اجازه دهند. می‌توانید از `PushManager` API برای اشتراک کاربران در پوش نوتیفیکیشن‌ها استفاده کنید.

مثال:

            
navigator.serviceWorker.ready.then(registration => {
  registration.pushManager.subscribe({
    userVisibleOnly: true,
    applicationServerKey: 'YOUR_PUBLIC_VAPID_KEY'
  })
  .then(subscription => {
    // Send subscription details to your server
    sendSubscriptionToServer(subscription);
  })
  .catch(error => {
    console.error('Failed to subscribe:', error);
  });
});

            

مهم: `YOUR_PUBLIC_VAPID_KEY` را با کلید VAPID (Voluntary Application Server Identification) واقعی خود جایگزین کنید. کلیدهای VAPID برای شناسایی سرور اپلیکیشن شما و اطمینان از ارسال امن پوش نوتیفیکیشن‌ها استفاده می‌شوند.

مدیریت پوش نوتیفیکیشن‌ها

هنگامی که یک پوش نوتیفیکیشن دریافت می‌شود، سرویس ورکر یک رویداد `push` را ارسال می‌کند. شما می‌توانید به این رویداد گوش دهید و نوتیفیکیشن را به کاربر نمایش دهید.

مثال:

            
self.addEventListener('push', event => {
  const payload = event.data ? event.data.text() : 'No payload';

  event.waitUntil(
    self.registration.showNotification('My PWA', {
      body: payload,
      icon: 'icon.png'
    })
  );
});

            

سفارشی‌سازی پوش نوتیفیکیشن‌ها

Notifications API به شما امکان می‌دهد ظاهر و رفتار پوش نوتیفیکیشن‌ها را سفارشی کنید. شما می‌توانید عنوان، متن، آیکون، بج (badge) و گزینه‌های دیگر را مشخص کنید.

مثال:

            
self.addEventListener('push', event => {
  const data = event.data.json();
  const title = data.title || 'My PWA';
  const options = {
    body: data.body || 'No message',
    icon: data.icon || 'icon.png',
    badge: data.badge || 'badge.png',
    vibrate: [200, 100, 200],
    data: { // Custom data that you can access when the user clicks the notification
      url: data.url || '/'
    },
    actions: [
      {action: 'explore', title: 'Explore this new world',
        icon: 'images/checkmark.png'},
      {action: 'close', title: 'Close',
        icon: 'images/xmark.png'},
    ]
  };

  event.waitUntil(self.registration.showNotification(title, options));
});


self.addEventListener('notificationclick', function(event) {
  event.notification.close();

  // Check if the user clicked on an action.
  if (event.action === 'explore') {
    clients.openWindow(event.notification.data.url);
  } else {
    // Default action: open the app.
    clients.openWindow('/');
  }
});

            

مثال: هشدار خبری

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

الگوهای پیشرفته سرویس ورکر

۱. تحلیل آفلاین (Offline Analytics)

رفتار کاربر را حتی زمانی که آفلاین است، با ذخیره داده‌های تحلیلی به صورت محلی و ارسال آن به سرور هنگام در دسترس بودن شبکه، ردیابی کنید. این کار را می‌توان با استفاده از IndexedDB و Background Sync انجام داد.

۲. نسخه‌بندی و به‌روزرسانی

یک استراتژی نسخه‌بندی قوی برای سرویس ورکر خود پیاده‌سازی کنید تا اطمینان حاصل شود که کاربران همیشه آخرین به‌روزرسانی‌ها را بدون اختلال در تجربه خود دریافت می‌کنند. از تکنیک‌های cache busting برای نامعتبر کردن دارایی‌های کش شده قدیمی استفاده کنید.

۳. سرویس ورکرهای ماژولار

کد سرویس ورکر خود را در ماژول‌ها سازماندهی کنید تا قابلیت نگهداری و خوانایی را بهبود بخشید. از ماژول‌های جاوااسکریپت (ESM) یا یک باندلر ماژول مانند Webpack یا Rollup استفاده کنید.

۴. کشینگ پویا (Dynamic Caching)

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

بهترین شیوه‌ها برای توسعه سرویس ورکر

نتیجه‌گیری

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

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

منابع بیشتر: