בשיעור ה-Codelab הזה תלמדו איך ליצור שרת התראות דחיפה, שלב אחר שלב. בסוף הקודלאב יהיה לכם שרת:
- מעקב אחרי מינויים להתראות (למשל, השרת יוצר רשומה חדשה במסד הנתונים כשלקוח מסכים לקבל התראות, ומוחק רשומה קיימת במסד הנתונים כשהלקוח מבטל את הסכמתו לכך).
- שליחת התראה ללקוח אחד
- שליחת הודעת Push לכל הלקוחות שנרשמו
המטרה של ה-Codelab הזו היא לעזור לכם ללמוד באמצעות עשייה, ולא מדברת הרבה על מושגים. במאמר איך פועלות התראות מוסבר על המושגים הקשורים להתראות.
קוד הלקוח של סדנת הקוד הזו כבר הושלם. בקודלאב הזה נטמיע רק את השרת. במאמר Codelab: פיתוח לקוח להתרעות מוסבר איך מטמיעים לקוח להתרעות.
ב-push-notifications-server-codelab-complete (מקור) תוכלו לראות את הקוד המלא.
תאימות דפדפן
ידוע שהקודלאב הזה פועל עם השילובים הבאים של מערכת הפעלה ודפדפן:
- Windows: Chrome, Edge
- macOS: Chrome, Firefox
- Android: Chrome, Firefox
ידוע שהקודלאב הזה לא פועל עם מערכות ההפעלה הבאות (או עם שילובים של מערכת הפעלה ודפדפן):
- macOS: Brave, Edge, Safari
- iOS
סטאק האפליקציות
- השרת מבוסס על Express.js.
- ספריית Node.js web-push מטפלת בכל הלוגיקה של התראות ה-push.
- נתוני המינוי נכתבים בקובץ JSON באמצעות lowdb.
אתם לא חייבים להשתמש באף אחת מהטכנולוגיות האלה כדי להטמיע התראות דחיפה. בחרנו בטכנולוגיות האלה כי הן מספקות חוויית Codelab אמינה.
הגדרה
קבלת עותק של הקוד שניתן לעריכה
לאורך הקודלאב הזה, נעזרים בעורך הקוד שמופיע משמאל להוראות האלה, שנקרא Glitch UI.
- לוחצים על רמיקס לעריכה כדי לערוך את הפרויקט.
מגדירים אימות
כדי להפעיל התראות דחיפה, צריך להגדיר את השרת והלקוח באמצעות מפתחות אימות. הסיבה לכך מפורטת במאמר חתימה על בקשות לפרוטוקול של התראות דחיפה באינטרנט.
- פותחים את טרמינל Glitch על-ידי לחיצה על Tools (כלים) ואז על Terminal.
- מריצים את הפקודה
npx web-push generate-vapid-keys
בטרמינל. מעתיקים את הערכים של המפתח הפרטי והמפתח הציבורי. - פותחים את
.env
ומעדכנים אתVAPID_PUBLIC_KEY
ואתVAPID_PRIVATE_KEY
. מגדירים אתVAPID_SUBJECT
ל-mailto:test@test.test
. צריך להקיף את כל הערכים האלו במירכאות כפולות. אחרי ביצוע העדכונים, קובץ.env
אמור להיראות כך:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
- סוגרים את טרמינל Glitch.
- פתיחת
public/index.js
. - מחליפים את
VAPID_PUBLIC_KEY_VALUE_HERE
בערך של המפתח הציבורי.
ניהול מינויים
הלקוח מטפל ברוב תהליך המינוי. הפעולות העיקריות שהשרת צריך לבצע הן לשמור מינויים חדשים להתראות בדחיפה ולמחוק מינויים ישנים. המינויים האלה מאפשרים לכם לשלוח הודעות ללקוחות בעתיד. למידע נוסף על תהליך ההרשמה, ראו הרשמה של הלקוח להתראות Push.
שמירת פרטי המינוי החדש
- כדי לראות תצוגה מקדימה של האתר, לוחצים על הצגת האפליקציה. לאחר מכן לוחצים על מסך מלא .
- לוחצים על Register service worker בכרטיסייה של האפליקציה. בתיבה 'סטטוס' אמורה להופיע הודעה דומה לזו:
Service worker registered. Scope: https://desert-cactus-sunset.glitch.me/
- בכרטיסייה של האפליקציה, לוחצים על Subscribe to push (הרשמה לעדכוני Push). סביר להניח שהדפדפן או מערכת ההפעלה שלכם יציג לכם שאלה אם אתם רוצים לאפשר לאתר לשלוח לכם התראות. לוחצים על אישור (או על הביטוי המקביל שמופיע בדפדפן או במערכת ההפעלה). בתיבת הסטטוס אמורה להופיע הודעה דומה לזו:
Service worker subscribed to push. Endpoint: https://fcm.googleapis.com/fcm/send/…
- כדי לחזור לקוד, לוחצים על View Source (הצגת המקור) בממשק המשתמש של Glitch.
- כדי לפתוח את יומני Glitch: לוחצים על Tools (כלים) ואז על Logs (יומנים). אמורה להופיע הערך
/add-subscription
ואחריו נתונים מסוימים./add-subscription
היא כתובת ה-URL שאליה הלקוח שולח בקשת POST כשהוא רוצה להירשם לקבלת התראות דחיפה. הנתונים הבאים הם פרטי המינוי של הלקוח שצריך לשמור. - פתיחת
server.js
. - מעדכנים את הלוגיקה של
/add-subscription
route handler באמצעות הקוד הבא:
app.post('/add-subscription', (request, response) => {
console.log('/add-subscription');
console.log(request.body);
console.log(`Subscribing ${request.body.endpoint}`);
db.get('subscriptions')
.push(request.body)
.write();
response.sendStatus(200);
});
מחיקת פרטי מינויים ישנים
- חוזרים לכרטיסיית האפליקציה.
- לוחצים על ביטול ההרשמה לקבלת התראות.
- בודקים שוב את יומני הבאגים. הכתובת
/remove-subscription
צריכה להופיע לצד פרטי המינוי של הלקוח. - מעדכנים את הלוגיקה של
/remove-subscription
route handler באמצעות הקוד הבא:
app.post('/remove-subscription', (request, response) => {
console.log('/remove-subscription');
console.log(request.body);
console.log(`Unsubscribing ${request.body.endpoint}`);
db.get('subscriptions')
.remove({endpoint: request.body.endpoint})
.write();
response.sendStatus(200);
});
שליחת התראות
כפי שמוסבר בקטע שליחת הודעת דחיפה, השרת לא שולח את הודעות הדחיפה ישירות ללקוחות. במקום זאת, הוא מסתמך על שירות דחיפה כדי לעשות זאת. בעיקרון, השרת רק מתחיל את תהליך הדחיפה של ההודעות ללקוחות על ידי שליחת בקשות לשירותי אינטרנט (בקשות לפרוטוקול דחיפה באינטרנט) לשירות אינטרנט (שירות הדחיפה) שבבעלות ספק הדפדפן שבו המשתמש משתמש.
- מעדכנים את הלוגיקה של ה-handler של המסלול ב-
/notify-me
עם הקוד הבא:
app.post('/notify-me', (request, response) => {
console.log('/notify-me');
console.log(request.body);
console.log(`Notifying ${request.body.endpoint}`);
const subscription =
db.get('subscriptions').find({endpoint: request.body.endpoint}).value();
sendNotifications([subscription]);
response.sendStatus(200);
});
- מעדכנים את הפונקציה
sendNotifications()
באמצעות הקוד הבא:
function sendNotifications(subscriptions) {
// TODO
// Create the notification content.
const notification = JSON.stringify({
title: "Hello, Notifications!",
options: {
body: `ID: ${Math.floor(Math.random() * 100)}`
}
});
// Customize how the push service should attempt to deliver the push message.
// And provide authentication information.
const options = {
TTL: 10000,
vapidDetails: vapidDetails
};
// Send a push message to each client specified in the subscriptions array.
subscriptions.forEach(subscription => {
const endpoint = subscription.endpoint;
const id = endpoint.substr((endpoint.length - 8), endpoint.length);
webpush.sendNotification(subscription, notification, options)
.then(result => {
console.log(`Endpoint ID: ${id}`);
console.log(`Result: ${result.statusCode}`);
})
.catch(error => {
console.log(`Endpoint ID: ${id}`);
console.log(`Error: ${error} `);
});
});
}
- מעדכנים את הלוגיקה של
/notify-all
route handler באמצעות הקוד הבא:
app.post('/notify-all', (request, response) => {
console.log('/notify-all');
response.sendStatus(200);
console.log('Notifying all subscribers');
const subscriptions =
db.get('subscriptions').cloneDeep().value();
if (subscriptions.length > 0) {
sendNotifications(subscriptions);
response.sendStatus(200);
} else {
response.sendStatus(409);
}
});
- חוזרים לכרטיסיית האפליקציה.
- לוחצים על ביטול ההרשמה לקבלת התראות ואז לוחצים שוב על הרשמה לקבלת התראות. צריך לעשות זאת כי, כפי שצוין קודם, Glitch מפעיל מחדש את הפרויקט בכל פעם שעורכים את הקוד, והפרויקט מוגדר למחוק את מסד הנתונים בזמן ההפעלה.
- לוחצים על אני רוצה לקבל התראות. אמורה להגיע התראה. השם צריך להיות
Hello, Notifications!
והתוכן צריך להיותID: <ID>
, כאשר<ID>
הוא מספר אקראי. - פותחים את האפליקציה בדפדפנים או במכשירים אחרים ומנסים להירשם לקבלת התראות בדפדפנים או במכשירים האלה, ואז לוחצים על הלחצן Notify all. אותה התראה אמורה להופיע בכל המכשירים שנרשמתם אליהם (כלומר, המזהה בגוף ההתראה צריך להיות זהה).
השלבים הבאים
- במאמר סקירה כללית על התראות דחיפה מוסבר בהרחבה איך התראות דחיפה פועלות.
- כדאי לקרוא את המאמר Codelab: בניית לקוח התראות כדי ללמוד איך לפתח לקוח שמבקש הרשאה לשליחת התראות, רושם את המכשיר לקבלת התראות ומשתמש ב-Service Worker כדי לקבל הודעות Push ולהציג את ההודעות כהתראות.