התראות באינטרנט הפתוח

אם תשאלו חדר של מפתחים אילו תכונות למכשירים ניידים חסרות באינטרנט, ההתראות תמיד מופיעות במיקום גבוה ברשימה.

התראות מאפשרות למשתמשים להביע הסכמה לקבלת עדכונים חשובים מאתרים אוהבים ומאפשרים לכם לעודד אותם לאינטראקציה חוזרת באמצעות תוכן מותאם אישית ומעניין.

החל מגרסה 42 של Chrome, ה-Push API וה- השירות Notification API זמין ל- למפתחים.

Push API ב-Chrome מסתמך על כמה פיסות טכנולוגיה שונות, כולל מניפסטים של אפליקציות אינטרנט ו-Service Workers. בפוסט הזה נבחן כל אחת מהטכנולוגיות האלה, אבל רק את המינימום המינימלי. כדי להתחיל להציג הודעות Push. כדי להבין טוב יותר חלק מהנושאים הבאים: תכונות אחרות של מניפסטים ויכולות אופליין של Service Worker, כדאי להיכנס לקישורים שלמעלה.

נבדוק גם מה יתווסף ל-API בגרסאות עתידיות של Chrome, ולבסוף, נשאל שאלות נפוצות.

הטמעה של העברת הודעות Push ב-Chrome

בקטע הזה מתואר כל שלב שצריך להשלים כדי לתמוך בדחיפה באפליקציית האינטרנט שלכם.

רישום Service Worker

יש תלות ב-Service Worker שיטמיע הודעות דחיפה באינטרנט. הסיבה לכך היא שכאשר מתקבלת הודעת דחיפה, הדפדפן יכול להפעיל Service Worker, שפועל ברקע ללא לפתוח דף חדש ולשלוח אירוע כדי להחליט איך לטפל בזה הודעה בדחיפה.

בהמשך מוצגת דוגמה לאופן שבו רושמים קובץ שירות (service worker) באפליקציית האינטרנט. מתי הרישום הסתיים בהצלחה, אנחנו קוראים ל-initialiseState(), נדבר על זה בקרוב.

var isPushEnabled = false;



window.addEventListener('load', function() {
    var pushButton = document.querySelector('.js-push-button');
    pushButton.addEventListener('click', function() {
    if (isPushEnabled) {
        unsubscribe();
    } else {
        subscribe();
    }
    });

    // Check that service workers are supported, if so, progressively
    // enhance and add push messaging support, otherwise continue without it.
    if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/service-worker.js')
    .then(initialiseState);
    } else {
    console.warn('Service workers aren\'t supported in this browser.');
    }
});

המטפל בלחיצה על לחצנים רושם את המשתמש ל'דחיפת הודעות' או מבטל את ההרשמה שלו. isPushEnabled הוא משתנה גלובלי שעוקב פשוט אחרי רשום כרגע כמנוי או לא. המערכת תתייחס לערכים האלה בכל שלב את קטעי הקוד.

לאחר מכן אנחנו בודקים אם יש תמיכה ב-Service Workers לפני הרישום של service-worker.js בעל לוגיקה לטיפול בהודעת דחיפה. כאן יש לנו פשוט אומרים לדפדפן שקובץ ה-JavaScript הזה הוא ה-Service Worker. לאתר שלנו.

הגדרת המצב הראשוני

דוגמה לחוויית המשתמש בהעברת הודעות ב-push שמופעלת ומושבתת ב-Chrome.

אחרי שה-Service Worker רשום, צריך להגדיר את המצב של ממשק המשתמש.

המשתמשים יצפו לממשק משתמש פשוט כדי להפעיל או להשבית הודעות דחיפה באתר שלך, והם יצפו לכך שהן יעודכנו בשינויים שמתרחשים. בעוד במילים אחרות, אם הן מאפשרות הצגת הודעות דחיפה לאתר, לעזוב ולחזור שבוע לאחר מכן, ממשק המשתמש שלכם אמור להדגיש שהודעות הדחיפה כבר מופעלות.

תוכלו למצוא כמה הנחיות לגבי חוויית המשתמש במסמך הזה, במאמר הזה נתמקד בהיבטים הטכניים.

בשלב הזה אתם עשויים לחשוב שיש רק שתי מדינות שצריך להתמודד איתן, מופעלת או מושבתת. עם זאת, יש מספר מדינות אחרות מסביב התראות שעליך להביא בחשבון.

תרשים שמדגיש את השיקולים השונים ואת מצב הדחיפה ב-Chrome

יש כמה ממשקי API שעלינו לבדוק לפני שנפעיל את הלחצן שלנו, אם הכול נתמך, אפשר להפעיל את ממשק המשתמש שלנו ולהגדיר את המצב הראשוני לציין אם שירות ה-Push הוא מנוי או לא.

מאחר שרוב הבדיקות גורמות להשבתת ממשק המשתמש שלנו, צריך להגדיר את המצב הראשוני מושבת. הפעולה הזו גם מונעת בלבול להיות בעיה ב-JavaScript של הדף, לדוגמה, קובץ ה-JS לא יכול להיות שהורד או שהמשתמש השבית את JavaScript.

<button class="js-push-button" disabled>
    Enable Push Messages
</button>

במצב הראשוני הזה, אנחנו יכולים לבצע את הבדיקות שצוינו למעלה initialiseState(). כלומר, אחרי שה-Service Worker נרשם.

// Once the service worker is registered set the initial state
function initialiseState() {
    // Are Notifications supported in the service worker?
    if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
    console.warn('Notifications aren\'t supported.');
    return;
    }

    // Check the current Notification permission.
    // If its denied, it's a permanent block until the
    // user changes the permission
    if (Notification.permission === 'denied') {
    console.warn('The user has blocked notifications.');
    return;
    }

    // Check if push messaging is supported
    if (!('PushManager' in window)) {
    console.warn('Push messaging isn\'t supported.');
    return;
    }

    // We need the service worker registration to check for a subscription
    navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
    // Do we already have a push message subscription?
    serviceWorkerRegistration.pushManager.getSubscription()
        .then(function(subscription) {
        // Enable any UI which subscribes / unsubscribes from
        // push messages.
        var pushButton = document.querySelector('.js-push-button');
        pushButton.disabled = false;

        if (!subscription) {
            // We aren't subscribed to push, so set UI
            // to allow the user to enable push
            return;
        }

        // Keep your server in sync with the latest subscriptionId
        sendSubscriptionToServer(subscription);

        // Set your UI to show they have subscribed for
        // push messages
        pushButton.textContent = 'Disable Push Messages';
        isPushEnabled = true;
        })
        .catch(function(err) {
        console.warn('Error during getSubscription()', err);
        });
    });
}

סקירה כללית קצרה של השלבים האלה:

  • אנחנו בודקים שהדומיין showNotification זמין ב-ServiceWorkerRegistration אב-טיפוס. בלי התג לא נוכל להציג התראה מ-Service Worker. כשמתקבלת הודעת דחיפה.
  • אנחנו בודקים מהו Notification.permission הנוכחי כדי לוודא שהוא לא "denied". המשמעות של ההרשאה שנדחתה היא שאי אפשר להציג התראות עד שהמשתמש ישנה את ההרשאה באופן ידני בדפדפן.
  • כדי לבדוק אם יש תמיכה בהעברת הודעות דחיפה, אנחנו בודקים ש-PushManager שזמינות באובייקט window.
  • לבסוף, השתמשנו בכתובת pushManager.getSubscription() כדי לבדוק אם כבר אם יש או אין. במקרה כזה, נשלח את פרטי המינוי אל השרת שלנו כדי לוודא שיש לנו את המידע הנכון ולהגדיר את ממשק המשתמש שלנו שדחיפה להעברת הודעות כבר מופעלת או לא. נבדוק אילו פרטים באובייקט המינוי בהמשך המאמר הזה.

אנחנו מחכים עד שהבעיה navigator.serviceWorker.ready תיפתר כדי לבדוק אם המינוי וכדי להפעיל את הלחצן כי הוא רק לאחר השירות. פעיל, כך שאפשר להירשם לקבלת הודעות דחיפה.

השלב הבא הוא לטפל כשהמשתמשים רוצים להפעיל הודעות דחיפה, אבל לפני שנוכל לעשות זאת, עלינו להגדיר פרויקט ב-Google Developer Console ולהוסיף כמה פרמטרים למניפסט כדי להשתמש בהעברת הודעות בענן ב-Firebase (FCM), שנקרא בעבר Google Cloud Messaging (GCM).

יצירת פרויקט ב-Firebase Developer Console

Chrome משתמש ב-FCM כדי לטפל בשליחה ובמסירה של הודעות דחיפה. אבל כדי להשתמש ב-FCM API, עליכם להגדיר פרויקט ב-Firebase Developer Console.

השלבים הבאים הם ספציפיים ל-Chrome, ל-Opera ל-Android ול-Samsung הדפדפן שבו הם משתמשים ב-FCM. בהמשך המאמר נדון באופן הפעולה הזה בדפדפנים אחרים.

יוצרים פרויקט מפתחים חדש ב-Firebase

כדי להתחיל, צריך ליצור פרויקט חדש בכתובת https://console.firebase.google.com/ באמצעות לחיצה על 'Create New Project' (יצירת פרויקט חדש).

צילום מסך חדש של פרויקט Firebase

צריך להוסיף שם לפרויקט, ליצור את הפרויקט והמערכת תעביר אותך לפרויקט לוח הבקרה:

דף הבית של פרויקט Firebase

במרכז הבקרה הזה, לוחצים על גלגל השיניים שמופיע בחלק העליון של שם הפרויקט בפינה השמאלית העליונה ולוחצים על 'Project Settings' (הגדרות הפרויקט).

תפריט הגדרות הפרויקט ב-Firebase

בדף ההגדרות, לוחצים על 'העברת הודעות בענן' .

תפריט העברת הודעות בענן בפרויקט Firebase

הדף הזה מכיל את מפתח ה-API להעברת הודעות Push, שבו נשתמש בהמשך, ואת מזהה השולח שצריך להזין בקובץ המניפסט של אפליקציית האינטרנט .

הוספת מניפסט של אפליקציית אינטרנט

לדחיפה, עלינו להוסיף קובץ מניפסט עם השדה gcm_sender_id, כדי לקבל את המינוי ל-Push ולהצליח. הפרמטר הזה נדרש רק על ידי Chrome, Opera ל-Android ו-Samsung Browser כדי שהם יוכלו להשתמש ב-FCM / GCM.

הדפדפנים האלה משתמשים ב-gcm_sender_id כשרושמים משתמשים במכשיר באמצעות FCM. זה אומר ש-FCM יכול לזהות את המכשיר של המשתמש ולבצע לוודא שמזהה השולח תואם למפתח ה-API התואם, ושלמשתמש יש אפשר לשרת שלך לשלוח להם הודעות בדחיפה.

בהמשך מופיע קובץ מניפסט פשוט במיוחד:

{
    "name": "Push Demo",
    "short_name": "Push Demo",
    "icons": [{
        "src": "images/icon-192x192.png",
        "sizes": "192x192",
        "type": "image/png"
        }],
    "start_url": "/index.html?homescreen=1",
    "display": "standalone",
    "gcm_sender_id": "<Your Sender ID Here>"
}

צריך להגדיר את הערך gcm_sender_id למזהה השולח מ: בפרויקט Firebase שלכם.

אחרי ששומרים את קובץ המניפסט בפרויקט (manifest.json הוא שימושי name), הפנה אותו מה-HTML שלך באמצעות התג הבא בחלק העליון של ה- הדף הזה.

<link rel="manifest" href="/manifest.json">

אם לא מוסיפים מניפסט אינטרנט עם הפרמטרים האלה, תתקבל חריגה כשמנסים לרשום את המשתמש לקבלת הודעות בדחיפה, והשגיאה "Registration failed - no sender id provided" או "Registration failed - permission denied".

הרשמה לקבלת הודעות Push

עכשיו, אחרי שהגדרת מניפסט, אפשר לחזור ל-JavaScript של האתרים.

כדי להירשם, צריך להפעיל את השיטה Subscription() בערוץ באובייקט PushManager, שאליו אתם ניגשים דרך ServiceWorkerRegistration

הפעולה הזו תבקש מהמשתמש לתת למקור הרשאה לשלוח דחיפה התראות. בלי ההרשאה הזו לא תוכלו להירשם

אם ההבטחה הוחזרה באמצעות ה-method Subscription(), מקבלים PushSubscription שתכיל נקודת קצה (endpoint).

יש לשמור את נקודת הקצה בשרת לכל משתמש, מכיוון שיהיה עליך לשלוח אליו הודעות דחיפה במועד מאוחר יותר.

הקוד הבא מבצע רישום של המשתמש לצורך העברת הודעות בדחיפה:

function subscribe() {
    // Disable the button so it can't be changed while
    // we process the permission request
    var pushButton = document.querySelector('.js-push-button');
    pushButton.disabled = true;

    navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
    serviceWorkerRegistration.pushManager.subscribe()
        .then(function(subscription) {
        // The subscription was successful
        isPushEnabled = true;
        pushButton.textContent = 'Disable Push Messages';
        pushButton.disabled = false;

        // TODO: Send the subscription.endpoint to your server
        // and save it to send a push message at a later date
        return sendSubscriptionToServer(subscription);
        })
        .catch(function(e) {
        if (Notification.permission === 'denied') {
            // The user denied the notification permission which
            // means we failed to subscribe and the user will need
            // to manually change the notification permission to
            // subscribe to push messages
            console.warn('Permission for Notifications was denied');
            pushButton.disabled = true;
        } else {
            // A problem occurred with the subscription; common reasons
            // include network errors, and lacking gcm_sender_id and/or
            // gcm_user_visible_only in the manifest.
            console.error('Unable to subscribe to push.', e);
            pushButton.disabled = false;
            pushButton.textContent = 'Enable Push Messages';
        }
        });
    });
}

בשלב זה אפליקציית האינטרנט שלך מוכנה לקבלת הודעת דחיפה, אבל לא יקרה עד שנוסיף Push event listener לקובץ ה-Service Worker.

האזנה לאירועי דחיפה ב-Service Worker

כשמתקבלת הודעת דחיפה (נסביר איך לשלוח דחיפה בפועל) הודעה בקטע הבא), אירוע Push יישלחו אל Service Worker, בשלב זה תצטרכו כדי להציג התראה.

self.addEventListener('push', function(event) {
    console.log('Received a push message', event);

    var title = 'Yay a message.';
    var body = 'We have received a push message.';
    var icon = '/images/icon-192x192.png';
    var tag = 'simple-push-demo-notification-tag';

    event.waitUntil(
    self.registration.showNotification(title, {
        body: body,
        icon: icon,
        tag: tag
    })
    );
});

הקוד הזה רושם האזנה לאירוע Push ומציג התראה עם כותרת מוגדרת מראש, טקסט גוף, סמל ותג התראה. פרט קטן אחד להדגיש בדוגמה הזו הוא event.waitUntil() . השיטה הזו לוקחת מובטח ומרחיב את משך החיים של גורם מטפל באירועים (או שאפשר לחשוב עליו ששומר על השירות) עד שההבטחה settated; במקרה הזה, ההבטחה שהועברה אל event.waitUntil היא ההבטחה שהוחזרה מ-showNotification().

תג ההתראה משמש בתור למזהה ייחודי להתראות ייחודיות. אם שלחנו שתי הודעות דחיפה נקודת קצה, עם עיכוב קצר ביניהן, והצגת התראות עם אותו תג, הדפדפן יציג את ההתראה הראשונה ויחליף אותה ההתראה השנייה כאשר הודעת הדחיפה מתקבלת.

אם רוצים להציג כמה התראות בו-זמנית ולהשתמש בתג אחר, או אין תיוג בכלל. בהמשך נתייחס לדוגמה מלאה יותר להצגת התראה פוסט. בינתיים נסתכל על זה בצורה פשוטה, ונראה אם מוצגת הודעת דחיפה התראה זו.

שליחת הודעת דחיפה

נרשמת לקבלת הודעות Push, וה-Service Worker מוכן להציג אז הגיע הזמן לשלוח הודעה דרך FCM.

השינוי הזה רלוונטי רק לדפדפנים שמשתמשים ב-FCM.

כששולחים את המשתנה PushSubscription.endpoint לשרת, ל-FCM היא מיוחדת. יש פרמטר בסוף כתובת ה-URL, הוא registration_id.

דוגמה לנקודת קצה:

https://fcm.googleapis.com/fcm/send/APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP

כתובת ה-URL של FCM היא:

https://fcm.googleapis.com/fcm/send

הערך בעמודה registration_id יהיה:

APA91bHPffi8zclbIBDcToXN_LEpT6iA87pgR-J-MuuVVycM0SmptG-rXdCPKTM5pvKiHk2Ts-ukL1KV8exGOnurOAKdbvH9jcvg8h2gSi-zZJyToiiydjAJW6Fa9mE3_7vsNIgzF28KGspVmLUpMgYLBd1rxaVh-L4NDzD7HyTkhFOfwWiyVdKh__rEt15W9n2o6cZ8nxrP

המצב הזה ספציפי לדפדפנים שמשתמשים ב-FCM. בדפדפן רגיל, פשוט לקבל נקודת קצה (endpoint), קוראים לנקודת הקצה הזו בצורה סטנדרטית הוא יעבוד בלי קשר לכתובת ה-URL.

כלומר בשרת שלכם תצטרכו לבדוק אם נקודת הקצה מיועד ל-FCM, ואם כן, מחלצים את ערך הרישום_id. כדי לעשות את זה ב-Python, יכול לעשות משהו כמו:

if endpoint.startswith('https://fcm.googleapis.com/fcm/send'):
    endpointParts = endpoint.split('/')
    registrationId = endpointParts[len(endpointParts) - 1]

    endpoint = 'https://fcm.googleapis.com/fcm/send'

אחרי שמקבלים את מזהה הרישום, אפשר לבצע קריאה ל-FCM API. שלך מסמכי עזר בנושא FCM API

ההיבטים העיקריים שכדאי לזכור כשמבצעים קריאה ל-FCM הם:

  • כותרת Authorization עם הערך key=&lt;YOUR_API_KEY&gt; צריך להגדיר כשקוראים ל-API, כאשר &lt;YOUR_API_KEY&gt; הוא מפתח API מפרויקט Firebase.
    • FCM משתמש במפתח ה-API כדי למצוא את מזהה השולח המתאים. צריך לוודא המשתמש נתן הרשאה לפרויקט שלכם, ולבסוף כדי לוודא שכתובת ה-IP של השרת נכללת ברשימת ההיתרים של הפרויקט הזה.
  • כותרת Content-Type מתאימה של application/json או application/x-www-form-urlencoded;charset=UTF-8, תלוי אם לשלוח את הנתונים כקובץ JSON או כנתוני טופס.
  • מערך של registration_ids – אלה מזהי הרישום שצריך לחלץ מנקודות הקצה אצל המשתמשים.

כדאי לעיין במסמכים שמסבירה איך לשלוח הודעות דחיפה מהשרת שלכם, אבל כדי לבדוק את ה-Service Worker אפשר להשתמש cURL כדי לשלוח הודעה בדחיפה לדפדפן שלך.

החלפה של &lt;YOUR_API_KEY&gt; ו-&lt;YOUR_REGISTRATION_ID&gt; בפקודת cURL הזו שלכם, ומריצים אותה מטרמינל.

אמורה להופיע התראה נהדרת:

    curl --header "Authorization: key=<YOUR_API_KEY>" --header
    "Content-Type: application/json" https://fcm.googleapis.com/fcm/send -d
    "{\"registration_ids\":[\"<YOUR_REGISTRA>TION_ID\"]}"
דוגמה להודעה מ-Chrome ל-Android.

במהלך פיתוח הלוגיקה של הקצה העורפי, חשוב לזכור שהכותרת Authorization הפורמט של גוף ה-POST הוא ספציפי לנקודת הקצה של FCM, לכן חשוב לזהות מתי נקודת הקצה (endpoint) מיועדת ל-FCM ומוסיפים את הכותרת ואת הפורמט של גוף ה-POST באופן מותנה. בדפדפנים אחרים (ובעתיד ב-Chrome) תצטרכו להטמיע Web Push Protocol.

החיסרון של ההטמעה הנוכחית של Push API ב-Chrome הוא לא יכולים לשלוח נתונים באמצעות הודעת דחיפה. לא, שום דבר. הסיבה לכך היא שבהטמעה עתידית, נתוני המטען הייעודי (payload) יצטרכו להיות מוצפנים לפני שהוא נשלח לנקודת הקצה של העברת הודעות בדחיפה. כך נקודת הקצה, לא משנה אם מדובר בספק Push, הוא לא יוכל להציג בקלות את התוכן של הודעה בדחיפה. פעולה זו מספקת הגנה גם מפני נקודות חולשה אחרות כמו אימות של אישורי HTTPS והתקפות אדם בתווך בין השרת וספק ה-Push. עם זאת, ההצפנה הזו עדיין לא נתמכת, לכן בינתיים תצטרכו לבצע אחזור כדי לקבל את המידע, לאכלס התראה.

דוגמה מלאה יותר לאירוע Push

ההודעה שראינו עד עכשיו היא די בסיסית, מבחינת הדוגמאות, זה די גרוע בכיסוי של תרחיש לדוגמה בעולם האמיתי.

בפועל, רוב האנשים ירצו לקבל מידע מהשרת שלהם לפני הצגת ההתראה. אלה יכולים להיות נתונים לאכלוס כותרת של התראה והודעה עם משהו ספציפי, או להתקדם לשלב הבא ושומרים במטמון חלק מהדפים או הנתונים, כך שכאשר המשתמש ילחץ על ההתראה, הכול זמין באופן מיידי כשהדפדפן נפתח - גם אם הרשת אינה זמינה באותו רגע.

בקוד הבא, אנחנו מאחזרים נתונים מ-API, ממירים את התגובה ולהשתמש בו כדי לאכלס את ההתראה שלנו.

self.addEventListener('push', function(event) {
    // Since there is no payload data with the first version
    // of push messages, we'll grab some data from
    // an API and use it to populate a notification
    event.waitUntil(
    fetch(SOME_API_ENDPOINT).then(function(response) {
        if (response.status !== 200) {
        // Either show a message to the user explaining the error
        // or enter a generic message and handle the
        // onnotificationclick event to direct the user to a web page
        console.log('Looks like there was a problem. Status Code: ' + response.status);
        throw new Error();
        }

        // Examine the text in the response
        return response.json().then(function(data) {
        if (data.error || !data.notification) {
            console.error('The API returned an error.', data.error);
            throw new Error();
        }

        var title = data.notification.title;
        var message = data.notification.message;
        var icon = data.notification.icon;
        var notificationTag = data.notification.tag;

        return self.registration.showNotification(title, {
            body: message,
            icon: icon,
            tag: notificationTag
        });
        });
    }).catch(function(err) {
        console.error('Unable to retrieve data', err);

        var title = 'An error occurred';
        var message = 'We were unable to get the information for this push message';
        var icon = URL_TO_DEFAULT_ICON;
        var notificationTag = 'notification-error';
        return self.registration.showNotification(title, {
            body: message,
            icon: icon,
            tag: notificationTag
        });
    })
    );
});

כדאי שוב להדגיש שהevent.waitUntil() מבטיח הבטחה וכתוצאה מכך ההבטחה מוחזרת על ידי showNotification(), כלומר ש-event listener לא ייצא עד לסיום הקריאה האסינכרונית של fetch(), וגם שמופיעה התראה.

תוצג לכם התראה גם אם מתרחשת שגיאה. הדבר כי אם לא, Chrome יציג הודעה גנרית משלו.

פתיחת כתובת URL כשמשתמש לוחץ על התראה

כשמשתמש לוחץ על התראה, נשלח אירוע notificationclick ב-Service Worker. בתוך ה-handler אפשר לבצע את הפעולות המתאימות, כמו מיקוד כרטיסייה או פתיחת חלון עם כתובת URL מסוימת:

self.addEventListener('notificationclick', function(event) {
    console.log('On notification click: ', event.notification.tag);
    // Android doesn't close the notification when you click on it
    // See: http://crbug.com/463146
    event.notification.close();

    // This looks to see if the current is already open and
    // focuses if it is
    event.waitUntil(
    clients.matchAll({
        type: "window"
    })
    .then(function(clientList) {
        for (var i = 0; i < clientList.length; i++) {
        var client = clientList[i];
        if (client.url == '/' && 'focus' in client)
            return client.focus();
        }
        if (clients.openWindow) {
        return clients.openWindow('/');
        }
    })
    );
});

דוגמה זו פותחת את הדפדפן לשורש המקור של האתר, על ידי התמקדות קיימת כרטיסיית מקור זהה אם קיימת, ואחרת פותחת כרטיסייה חדשה.

יש לנו פוסט ייעודי לכמה דברים שאפשר לעשות בעזרת ה-Notification API.

ביטול ההרשמה למכשיר של משתמש

נרשמת למכשיר של משתמש והוא מקבל הודעות דחיפה, אבל איך לבטל את ההרשמה?

הדבר העיקרי שנדרש כדי לבטל את ההרשמה למכשיר של משתמש הוא להתקשר אל השיטה unsubscribe() ב PushSubscription ולהסיר את נקודת הקצה מהשרתים (רק כדי שלא שליחת הודעות דחיפה שאתה יודע שלא יתקבלו). הקוד שבהמשך בדיוק כך:

function unsubscribe() {
    var pushButton = document.querySelector('.js-push-button');
    pushButton.disabled = true;

    navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
    // To unsubscribe from push messaging, you need get the
    // subscription object, which you can call unsubscribe() on.
    serviceWorkerRegistration.pushManager.getSubscription().then(
        function(pushSubscription) {
        // Check we have a subscription to unsubscribe
        if (!pushSubscription) {
            // No subscription object, so set the state
            // to allow the user to subscribe to push
            isPushEnabled = false;
            pushButton.disabled = false;
            pushButton.textContent = 'Enable Push Messages';
            return;
        }

        var subscriptionId = pushSubscription.subscriptionId;
        // TODO: Make a request to your server to remove
        // the subscriptionId from your data store so you
        // don't attempt to send them push messages anymore

        // We have a subscription, so call unsubscribe on it
        pushSubscription.unsubscribe().then(function(successful) {
            pushButton.disabled = false;
            pushButton.textContent = 'Enable Push Messages';
            isPushEnabled = false;
        }).catch(function(e) {
            // We failed to unsubscribe, this can lead to
            // an unusual state, so may be best to remove
            // the users data from your data store and
            // inform the user that you have done so

            console.log('Unsubscription error: ', e);
            pushButton.disabled = false;
            pushButton.textContent = 'Enable Push Messages';
        });
        }).catch(function(e) {
        console.error('Error thrown while unsubscribing from push messaging.', e);
        });
    });
}

שמירה על עדכניות המינוי

ייתכן שהמינויים לא יסונכרנו בין FCM לשרת שלכם. כדאי לוודא השרת מנתח את גוף התגובה של בקשת השליחה POST ב-FCM API, תוצאות error:NotRegistered ו-canonical_id, כמו שמוסבר במסמכי התיעוד של FCM.

בנוסף, ייתכן שהמינויים לא יסונכרנו בין ה-Service Worker השרת. לדוגמה, לאחר הרשמה/ביטול הרשמה בהצלחה, בעיה חיבור לרשת עשוי למנוע מכם לעדכן את השרת. או שמשתמש לבטל את ההרשאה לשליחת התראות, פעולה שגורמת לביטול הרשמה אוטומטי. הכינוי במקרים כאלה על ידי בדיקת התוצאות serviceWorkerRegistration.pushManager.getSubscription() מדי פעם (למשל, בטעינת דף) ולסנכרן אותו עם השרת. כדאי גם: להירשם מחדש באופן אוטומטי אם כבר אין לכם מינוי Notification.permission == 'granted'.

בsendSubscriptionToServer() יהיה עליך לשקול איך לטפל בקשות רשת שנכשלו בעדכון endpoint. פתרון אחד הוא כדי לעקוב אחרי המצב של endpoint בקובץ Cookie כדי לקבוע אם השרת שלכם צריך את הפרטים העדכניים או לא.

כל השלבים האלה מובילים ליישום מלא של העברת הודעות Push באינטרנט ב-Chrome 46. עדיין יש תכונות ספציפיות שיקלו על השימוש (כמו ממשק API רגיל להפעלת הודעות Push), אבל הגרסה הזו מאפשרת מתחילים ליצור כבר היום הודעות דחיפה לאפליקציות האינטרנט שלכם.

איך לנפות באגים באפליקציית האינטרנט

במהלך הטמעת הודעות Push, הבאגים יופיעו באחד משני מקומות: בדף שלכם או קובץ השירות (service worker).

ניתן לנפות באגים בדף באמצעות DevTools. לניפוי באגים ב-Service Worker יש לך שתי אפשרויות:

  1. עוברים אל chrome://inspect > קובצי שירות (service worker). התצוגה הזו לא מספקת הרבה מידע מלבד עובדי השירות שפועלים כרגע.
  2. עוברים אל chrome://serviceworker-internals ומכאן אפשר לצפות של Service of Service Worker ולראות שגיאות, אם יש כאלה. הדף הזה זמנית, עד שלכלי הפיתוח תהיה קבוצת תכונות דומה.

אחד הטיפים הכי טובים שאני יכול לתת לכל מי שלא מתמצאים ב-Service Worker הוא שימוש בתיבת הסימון שנקראת "פתיחת חלון כלי הפיתוח והשהיית הפעלת JavaScript on service worker start לניפוי באגים." תיבת הסימון הזו תוסיף נקודת עצירה ב- ההתחלה של ה-Service worker ו-pause הביצוע, זה מאפשר לכם להמשיך או לעבור על הסקריפט של Service Worker ולבדוק אם הגעתם או בעיות.

צילום מסך שמראה איפה תיבת הסימון של ביצוע ההשהיה נמצאת ב-serviceworker-internal.

אם נראה שיש בעיה בין FCM לאירוע דחיפה של Service Worker, אין הרבה שניתן לעשות כדי לנפות את הבאגים שגרמו לבעיה, כדי לראות אם Chrome קיבל משהו. הדבר החשוב ביותר הוא לוודא תגובה מ-FCM מבוצעת בהצלחה כשהשרת מבצע קריאה ל-API. הוא ייראה משהו כמו:

{"multicast_id":1234567890,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1234567890"}]}

שימו לב לתשובה "success": 1. אם במקום זאת מופיע כשל, טוען שמשהו לא תקין במזהה הרישום של FCM ההודעה לא נשלחת ל-Chrome.

קובצי Service Workers של ניפוי באגים ב-Chrome ל-Android

נכון לעכשיו, לא ברור מאליו של עובדי שירות ב-Chrome ל-Android לנפות באגים. עליך לנווט אל chrome://inspect, למצוא את המכשיר שלך ולחפש פריט בשם ' Worker pid:.... ' שכולל את כתובת ה-URL של השירות. עובד.

צילום מסך שמראה את המיקום של עובדי שירות בבדיקה של Chrome

חוויית המשתמש להתראות בדחיפה

צוות Chrome הכין מסמך של שיטות מומלצות לקבלת התראות על חוויית המשתמש, וגם מסמך המכסה חלק של מקרי הקצה כשעובדים עם התראות.

העתיד של העברת הודעות ב-Chrome והאינטרנט הפתוח

הקטע הזה עוסק בקצת פרטים לגבי חלק ממכשירי Chrome לחלקים ספציפיים בהטמעה, שצריך להיות מודעים להם, ולהבין איך יהיה שונה מהטמעות אחרות של דפדפנים.

פרוטוקול Web Push ונקודות קצה (endpoints)

היופי בתקן Push API הוא היכולת ליישם endpoint, מעבירים אותן לשרת ושולחים דחיפה הודעות על ידי הטמעת פרוטוקול דחיפת האינטרנט.

Web Push Protocol הוא תקן חדש שספקי דחיפה יכולים להטמיע, באופן שמאפשר למפתחים לא לחשוש מי ספק ה-Push. הוא חוסך את הצורך להירשם למפתחות API ולשלוח גדול יותר של נתונים, כמו שמשתמשים ב-FCM.

Chrome היה הדפדפן הראשון שהטמיע את Push API ו-FCM לא הטמיע תומכות ב-Web Push Protocol, ולכן Chrome דורש gcm_sender_id ואתם צריכים להשתמש ב-API הרגוע ל-FCM.

המטרה הסופית של Chrome היא להתקדם לשימוש בפרוטוקול Web Push Protocol עם Chrome ו-FCM.

עד אז, צריך לזהות את נקודת הקצה &quot;https://fcm.googleapis.com/fcm/send&quot; ולטפל בהם בנפרד מנקודות קצה אחרות, כלומר לפרמט את נתוני המטען הייעודי (payload) בפורמט ספציפית ולהוסיף את מפתח ההרשאה.

איך להטמיע את Web Push Protocol

Firefox Nightly פועל כרגע לביצוע דחיפה, וסביר להניח שהוא יהיה הדפדפן הראשון כדי להטמיע את Web Push Protocol.

שאלות נפוצות

איפה מופיעים המפרט?

https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ https://w3c.github.io/push-api/ https://notifications.spec.whatwg.org/

האם אפשר למנוע כפילויות של התראות אם לנוכחות שלי באינטרנט יש כמה מקורות, או אם יש לי גם נוכחות באינטרנט וגם נוכחות מותאמת?

אין כרגע פתרון לבעיה הזו, אבל אפשר לעקוב אחרי ההתקדמות ב-Chromium.

התרחיש האידיאלי הוא מזהה סוג כלשהו של מכשיר של משתמש, ואז בצד השרת, מתאימים בין מזהי המינוי של אפליקציות האינטרנט ושל אפליקציות האינטרנט לבין המזהים ולהחליט לאיזה מהם לשלוח הודעת דחיפה. אפשר לעשות את זה דרך גודל המסך, של המכשיר, השיתוף של מפתח שנוצר בין אפליקציית האינטרנט לבין אפליקציית הנייטיב, לכל גישה יש יתרונות וחסרונות.

למה צריך לציין gcm_sender_id?

פעולה זו נדרשת כדי ש-Chrome, Opera ל-Android ודפדפן Samsung יוכלו להשתמש ב-API של Firebase להעברת הודעות בענן (FCM). המטרה היא להשתמש פרוטוקול Web Push Protocol אם התקן הוא סופי ו-FCM יכול לתמוך בו.

למה לא להשתמש ב-Web Sockets או באירועים שנשלחו על ידי שרת (EventSource)?

היתרון של השימוש בהודעות דחיפה הוא שגם אם הדף שלך סגור, Service Worker יתעורר ויוכל להציג התראה. רכיבי Web Socket החיבור של ו-EventSource נסגר כשהדף או הדפדפן נסגר.

מה אם אין לי צורך בשליחת אירועים ברקע?

אם אתם לא צריכים מסירה ברקע, Web Sockets הם אפשרות מצוינת.

מתי אפשר להשתמש בדחיפה בלי להציג התראות (כלומר, דחיפת רקע שקטה)?

אין כרגע לוח זמנים שבו היא תהיה זמינה, אבל יש כוונת הטמעת סנכרון ברקע ולמרות שהדבר לא מוחלט או מפורט, ישנו דיון לגבי הפעלת דחיפה שקטה עם סנכרון ברקע.

למה נדרש HTTPS? איך אפשר לעקוף את זה במהלך הפיתוח?

קובצי שירות (service worker) דורשים מקורות מאובטחים כדי להבטיח שהסקריפט של Service Worker יתבצע היא מהמקור המיועד ולא הגיעה מאדם בתווך מתקפה. בשלב זה, המשמעות היא שימוש ב-HTTPS באתרים פעילים, למרות ש-localhost פועלים במהלך הפיתוח.

איך נראית התמיכה בדפדפן?

Chrome תומך בגרסה היציבה שלו, והעבודה על Mozilla מתבססת על דפדפן Firefox Nightly. מידע נוסף זמין בבאג הטמעת Push API ואפשר לעקוב אחרי ההטמעה של ההתראות כאן.

האם אפשר להסיר התראה אחרי פרק זמן מסוים?

כרגע זה לא אפשרי אבל אנחנו מתכננים להוסיף תמיכה כדי רשימה של ההתראות הגלויות כרגע. אם יש לכם תרחיש לדוגמה כדי להגדיר תפוגה של התראה לאחר הצגתה, נשמח לדעת מה זה, אז הוסיפו הערה ונחזיר אותה לצוות Chrome.

אם צריך רק למנוע שליחה של התראה למשתמש לאחר תקופה מסוימת, ולא משנה כמה זמן ההתראה נשארת אפשר להשתמש בזמן אמת (ttl) של FCM, מידע נוסף זמין כאן.

מהן המגבלות של העברת הודעות Push ב-Chrome?

בפוסט הזה יש כמה מגבלות:

  • השימוש של Chrome ב-CCM בתור שירות דחיפה יוצר בדרישות שלנו. אנחנו עובדים ביחד כדי לבדוק אם ניתן להסיר חלק מהבעיות האלה לעתיד.
  • צריך להציג התראה כשמקבלים הודעה.
  • ב-Chrome במחשב יש אזהרה: אם Chrome לא פועל, הודעות Push לא יתקבלו. המצב הזה שונה מ-ChromeOS ול-Android, שבהם הודעות Push יתקבלו תמיד.

לא כדאי להשתמש ב-Permissions API?

Permissions API מוטמע ב-Chrome, אבל הוא לא יהיה זמין בהכרח בכל הדפדפנים. מידע נוסף זמין כאן.

למה Chrome לא פותח את הכרטיסייה הקודמת כשלוחצים על התראה?

הבעיה הזו משפיעה רק על דפים שלא בשליטת שירות מסוים כרגע עובד. אפשר לעיין כאן במידע נוסף.

מה קורה אם התראה לא מעודכנת עד למועד שבו המכשיר של המשתמש קיבל את הדחיפה?

תמיד צריך להציג התראה כשמקבלים הודעה. בתרחיש שבו רוצים לשלוח התראה, אבל האפשרות הזו שימושית בלבד. למשך תקופה מסוימת, אפשר להשתמש בפונקציה 'time_to_live' פרמטר ב-CCM כך ש-FCM לא ישלח את ההודעה אם עבר מועד התפוגה.

פרטים נוספים זמינים כאן.

מה קורה אם שולחים 10 הודעות Push אבל רוצים שהמכשיר יקבל רק הודעה אחת?

ב-FCM יש 'מפתח_כווץ' שאפשר להשתמש בו כדי להורות ל-FCM להחליף כל הודעה עם אותו 'כווץ_key', יחד עם ההודעה החדשה.

פרטים נוספים זמינים כאן.