שימוש ב-WebSockets ב-Service Workers

במדריך הזה נסביר איך להתחבר ל-WebSocket ב-service worker של תוסף Chrome. אתם יכולים לראות דוגמה לעבודה ב-GitHub.

רקע

החל מגרסה 116 של Chrome, יש תמיכה משופרת ב-WebSockets בשירותי העובדים של התוספים. בעבר, קובץ שירות (service worker) היה במצב לא פעיל למרות שחיבור WebSocket היה פעיל אם לא התרחשו אירועים אחרים של תוסף במשך 30 שניות. הפעולה הזו תסגור את קובץ השירות (service worker) ותסגור את החיבור של WebSocket. לקבלת רקע נוסף על מחזור החיים של קובץ שירות בתוסף, ניתן לקרוא את המדריך ל-service worker בנושא תוסף).

החל מגרסה 116 של Chrome, אפשר לשמור על פעילות של שירות עבודה עם חיבור WebSocket על ידי החלפת הודעות בחלון הפעילות של שירות העבודה למשך 30 שניות. אפשר להפעיל אותן מהשרת או מהתוסף שלכם. בדוגמה הבאה נשלח לשרת הודעה קבועה מהתוסף ל-Chrome כדי להבטיח שה-Service Worker יישאר בחיים.

דוגמה: Keepalive של WebSocket

קודם כול, צריך לוודא שהתוסף יפעל רק בגרסאות Chrome שתומכות ב-WebSockets ב-service workers. לשם כך, מגדירים את גרסת Chrome המינימלית ל-116 במניפסט:

manifest.json:

{
  ...
  "minimum_chrome_version": "116",
  ...
}

לאחר מכן נוכל לשמור על פעילות של ה-service worker על ידי שליחת הודעת keepalive כל 20 שניות. ה-keepalive מופעל ברגע ש-service worker מתחבר ל-WebSocket. הדוגמה הבאה של לקוח WebSocket רושמת הודעות וקריאות ל-keepAlive() כשהאירוע onopen מופעל:

service-worker.js

let webSocket = null;

function connect() {
  webSocket = new WebSocket('wss://example.com/ws');

  webSocket.onopen = (event) => {
    console.log('websocket open');
    keepAlive();
  };

  webSocket.onmessage = (event) => {
    console.log(`websocket received message: ${event.data}`);
  };

  webSocket.onclose = (event) => {
    console.log('websocket connection closed');
    webSocket = null;
  };
}

function disconnect() {
  if (webSocket == null) {
    return;
  }
  webSocket.close();
}

בתוך keepAlive() אנחנו משתמשים ב-setInterval(...) כדי לשלוח פינג לשרת באופן קבוע כשיש חיבור WebSocket פעיל:

function keepAlive() {
  const keepAliveIntervalId = setInterval(
    () => {
      if (webSocket) {
        webSocket.send('keepalive');
      } else {
        clearInterval(keepAliveIntervalId);
      }
    },
    // Set the interval to 20 seconds to prevent the service worker from becoming inactive.
    20 * 1000 
  );
}