Firebase Cloud Messaging for Web (JavaScript library) แบบง่ายๆ [Updated 2016–11–27]
บทนำ
ณ นาทีนี้คงจะพูดได้เต็มปากแล้วว่า ใครไม่รู้จัก Firebase ไม่น่าจะนับว่าเป็น Developer สาย Web/Mobile นะครับ
หลังจาก Google ได้เปิดตัว Firebase อย่างยิ่งใหญ่เมื่องาน Google I/O 2016 ที่ผ่านมา ก็สร้างความฮือฮาให้กับบรรดา Developer สาย Web/Mobile เป็นอย่างมาก เพราะด้วย Features หลายๆอย่างที่มี ทำให้การเสกแอพนั้นง่ายขึ้นมาก ซึ่งหนึ่งใน Feature ที่สำคัญตัวหนึ่งนั่นก็คือ Firebase Cloud Messaging (FCM)
ขออธิบายสั้นๆ เกี่ยวกับ FCM สำหรับคนที่ยังไม่รู้จัก FCM นะครับ เจ้า FCM เนี่ย เป็นเครื่องมือตัวนึงที่ Google รีแบรนด์มาจาก Google Cloud Messaging (GCM) หน้าที่ของมันก็คือ เอาไว้ส่ง Push Message ครับ โดยที่ผู้รับ Message ตอนนี้ก็ครอบคลุมแทบจะทุก Platform แล้วครับ
แต่เหมือนฟ้าสั่งสวรรค์แกล้ง เมื่อ ณ ตอนเปิดตัว ตัว FCM มี Library ออกมาแค่ Android และ iOS เท่านั้น ไม่มีของ Web ออกมาด้วย ก็ทำให้ชาว Developer สาย Mobile ชอกช้ำระกำทรวงกันไป (จริงๆแล้ว ก็ใช้ Web Worker ทำงานได้ตามปกตินะครับ แต่ขั้นตอนการทำเนี่ยมันเยอะ) แต่ ณ วันนี้ ชาว Developer สาย Mobile ก็ยิ้มออกกันแล้ว เมื่อ Google ได้ออก JavaScript Library มาแล้ว ฉะนั้น ใครที่นอกใจไปใช้ของเจ้าอื่น ตอนนี้ Google เค้าง้อแล้วนะครับ กลับมาเถอะนะครับ
อย่าพึ่งดีใจไปนะครับ เพราะว่า Browser ที่รองรับตอนนี้มีเพียง
- Chrome: 50+
- Firefox: 44+
- Opera Mobile: 37+
ส่วน Edge ทางฝั่ง Browser เองกำลังจะรองรับนะครับ (เมื่อไรไม่รู้นะ)
ก่อนจะเข้าสู่ช่วง “ลงมือทำ” ขอให้เช็คความรู้กันซักนิดนะครับ สิ่งที่เราจะทำกันต่อไปนี้ ต้องใช้ความรู้ดังต่อไปนี้
- JavaScript
- HTML
- POST request
- Firebase account + Firebase Project
ในเนื้อหาช่วง “ลงมือทำ” จะแบ่งเนื้อหาเป็น 3 ส่วน นั่นคือ
- Setup web
- Send push message
- Playing with web notification
เมื่อพร้อมแล้ว ก็ลงมือกันเลย เย่!
ลงมือทำ
1. Setup web
ในขั้นตอนนี้สิ่งที่ต้องทำคือ สร้าง Firebase project หรือจะใช้ที่มีอยู่แล้วก็ได้นะครับ ในตัวอย่างขอใช้ชื่อ Project ว่า “Hello Web FCM” นะครับ
ก่อนที่จะไปไกลกว่านี้ ต้องอย่างลืมว่า Web จะรับ Push ได้นั้น Web เราต้องเป็น HTTPS นะครับ เพราะฉะนั้น ในตัวอย่างนี้จะใช้ Firebase Hosting ทำนะครับ
ต่อมาขออนุญาตเตรียม Web ของเราผ่าน Firebase Hosting ให้เรียบร้อยก่อนนะครับ ด้วยคำสั่ง
firebase init
ก็ตั้งค่าไปครับ ตอนนี้ไม่มีอะไรมาก หลังจากเสร็จเรียบร้อยแล้วนะครับ ให้ลองใช้คำสั่ง
firebase serve
เพื่อทดสอบดูก่อนนะครับว่า Web เราพร้อมหรือยัง ซึ่งควรจะได้หน้าตาแบบนี้นะครับ
ต่อมานะครับ เราต้องใส่ JavaScript ให้เว็บเราก่อน ซึ่งจะต้องทำตามนี้
<script src="https://www.gstatic.com/firebasejs/3.5.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.5.0/firebase-messaging.js"></script></script>
<script>
// Initialize Firebase
// TODO: Replace with your project's customized code snippet
var config = {
apiKey: "<API_KEY>",
authDomain: "<PROJECT_ID>.firebaseapp.com",
databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
storageBucket: "<BUCKET>.appspot.com",
messagingSenderId: "<SENDER_ID>",
};
firebase.initializeApp(config);
</script>
ในตัวอย่างนี้เราต้องการใช้แค่ firebase-app.js กับ firebase-messaging.js ก็พอนะครับ ส่วนค่า Setting ก็ของใครของมันนะครับ
ต่อมาต้องสร้างไฟล์ manifest.json ขึ้นมานะครับ วางไว้ระดับเดียวกับ index.html นะครับ โดยไฟล์ manifest.json ให้มีเนื้อหาแบบนี้นะครับ ห้ามแก้นะ
{
“//”: “Some browsers will use this to enable push notifications.”,
“//”: “It is the same for all projects, this is not your project’s sender ID”,
“gcm_sender_id”: “103953800507”
}
เจ้าไฟล์ manifest.json เนี่ยมันเป็น Configuration file ที่ตัว FCM ต้องใช้นะครับ
ต่อมาเราจะสร้าง Object ของ Firebase messaging กันนะครับ ด้วยคำสั่ง
// Retrieve Firebase Messaging object.
const messaging = firebase.messaging();
เอาไปต่อตรงบรรทัด firebase.initializeApp(config); เลยก็ได้นะครับ
ต่อมาเราจะโมหน้าเว็บเรานิดนึง กับวาง JavaScript เพื่อสั่ง Subscribe นะครับ
<div id=”message”>
<h1>Hello Web FCM</h1>
<p>Click on Subscribe button to hello world!</p>
<ul>
<li><a href=”javascript:subscribeFCM()”>Subscribe</a></li>
</ul>
<h3>Token</h3>
<p id=”token”></p>
</div><script type=”text/javascript”>
function subscribeFCM() {
messaging.requestPermission()
.then(function() {
console.log(‘Notification permission granted.’);
// TODO(developer): Retrieve a Instance ID token for use with FCM.
// …
})
.catch(function(err) {
console.log(‘Unable to get permission to notify. ‘, err);
});
}
</script>
อธิบาย ในส่วนของ HTML เราเปลี่ยน Action ของ Link ให้ไปเรียก JavaScript function ที่เราสร้างขึ้นมา ชื่อว่า subscribeFCM() นะครับ ส่วน JavaScript นั้นทำงานเพียงแค่สั่ง Subscribe ด้วยการขอ Permission นะครับ เพียงเท่านี้ Web ของเราก็พร้อมสำหรับการ Subscribe แล้วครับ
ในการใช้งานเมื่อเรากดที่ปุ่ม Subscribe ตัว Browser จะมี Popup มาถามนะครับ
ซึ่งหากเปิด Web Console ดูประกอบไปด้วย เราจะเห็นข้อความลักษณะแบบนี้
ซึ่งมันสัมพันธ์กับ messaging.requestPermission() นะครับ
ต่อมาเราจะเอา Token ออกมาใช้งานนะครับ แต่ต่อจากนี้เราจะย้ายไปใช้ Firebase server แล้วนะครับ เราจะไม่ใช้ Localhost ทำละ
firebase deploy
เมื่อพร้อมแล้วเราจะมาเพิ่มไฟล์ กับเพิ่ม Code อีกเล็กน้อยก่อนนะครับ
ให้ไปเอาไฟล์ firebase-messaging-sw.js มาจาก https://github.com/firebase/quickstart-js/blob/master/messaging/firebase-messaging-sw.js นะครับ แล้ววางไว้ที่เดียวกับ index.html นะครับ อ่อ ในไฟล์นี้อย่าลืมเปลี่ยนค่า SenderId นะครับ เสร็จแล้วก็ไปปรับ Code ในไฟล์ index.html ตามนี้
<div id=”message”>
<h1>Hello Web FCM</h1>
<p>Click on Subscribe button to hello world!</p>
<ul>
<li><a href=”javascript:subscribeFCM()”>Subscribe</a></li>
<li><a href=”javascript:showToken()”>Show Token</a></li>
</ul>
<h3>Token</h3>
<p id=”token”></p>
</div><script type=”text/javascript”>
function subscribeFCM() {
messaging.requestPermission()
.then(function() {
console.log(‘Notification permission granted.’);
})
.catch(function(err) {
console.log(‘Unable to get permission to notify. ‘, err);
});
}function showToken() {
// Get Instance ID token. Initially this makes a network call, once retrieved
// subsequent calls to getToken will return from cache.
messaging.getToken()
.then(function(currentToken) {
if (currentToken) {
console.log(“currentToken”, currentToken);
$(“#token”).html(currentToken);
} else {
// Show permission request.
console.log(‘No Instance ID token available. Request permission to generate one.’);
$(“#token”).html(“foo”);
}
})
.catch(function(err) {
console.log(‘An error occurred while retrieving token. ‘, err);
});
}messaging.onTokenRefresh(function() {
messaging.getToken()
.then(function(refreshedToken) {
console.log(‘Token refreshed.’);
$(“#token”).html(refreshedToken);
})
.catch(function(err) {
console.log(‘Unable to retrieve refreshed token ‘, err);
});
});
</script>
สั่ง Deploy ใหม่ให้เรียบร้อย แล้วหน้าเว็บเราจะเปลี่ยนไปนิดหน่อยนะครับ
ก็ลองกดๆดูได้ครับ ไม่พัง ค่า Token ที่ได้เนี่ย เดี๋ยวเราจะต้องเอาไปใช้ตอนส่ง Push message นะครับ
ก่อนที่จะไปลองส่ง Push message ขอให้เพิ่ม Code ในไฟล์ index.html อีกนิดนะครับ
messaging.onMessage(function(payload) {
console.log(“Message received. “, payload);
});
Code ชุดนี้จะทำงานเมื่อเราเปิดเว็บอยู่นะครับ (Foreground) แล้วถ้าเราไม่ได้เปิดเว็บอยู่ล่ะ? (Background) ก็ไฟล์ firebase-messaging-sw.js นั่นแหละครับ ที่รับหน้าที่จัดการไป อย่าลืมสั่ง Deploy ใหม่ให้เรียบร้อยนะครับ
2. Send push message
คราวนี้มาเรื่องการส่ง Push message กันนะครับ มันก็ไม่วายมีเรื่องให้เราลำบากกันนิดหน่อยนะครับเพราะว่า
เรายังสั่งยิง Push ออกมาจากหน้า Console ของ Firebase ไม่ได้นะครับ เข้าใจว่ายังทำไม่เสร็จ (ณ วันที่ ๑๘ ตุลาคม ๒๕๕๙) แต่ไม่เป็นไรครับ มันไม่เกินความสามารถของพวกเราเหล่า Dev หรอก
งานนี้ Postman จะมารับหน้าที่ต่อนะครับ
เราจะสั่งยิง Push ผ่านทาง REST service กันนะครับ ด้วยชุดคำสั่ง
https://fcm.googleapis.com/fcm/send
Content-Type: application/json
Authorization: key=AIzaSyC...akjgSX0e4
{ "notification": {
"title": "Background Message Title",
"body": "Background message body",
"click_action" : "https://dummypage.com"
},
"to" : "eEz-Q2sG8nQ:APA91bHJQRT0JJ..."
}
ใส่ค่าใน Postman ให้ถูกต้อง
แล้วกด Send เบาๆ ใช้เวลา 1 อึดใจ ตัว FCM จะตอบกลับมาว่าสำเร็จหรือไม่สำเร็จนะครับ เมื่อเรายิงออกมาแล้วนะครับ ถ้าเราเปิดเว็บอยู่มันจะมาตกที่ messaging.onMessage(…) ได้ผลลัพท์ตามนี้
สังเกตุตรง payload ที่เราได้มานะครับ เราใส่อะไรไปใน “notification” มันก็มาทั้งหมดเลย ก็เอาไปปรับใช้กันได้ตามสถานการณ์กันตามใจได้เลย
ถ้าในกรณีที่เราไม่ได้เปิดเว็บอยู่ก็ …
ก็จะเป็นแบบนี้นะครับ
3. Playing with web notification
ในหัวข้อนี้จะเน้นเรื่องการประยุกต์ใช้งานนะครับ เนื่องจากตัว Web FCM เนี่ยยังไม่มี subscribeToTopic(…) แบบ Android หรือ iOS (ณ วันที่ ๑๘ ตุลาคม ๒๕๕๙) ฉะนั้นถ้าเราอยากทำ Topic ก็มี 2 ทางคือ 1. เราต้องทำ Server เพื่อเก็บ Token เอง แล้วก็ระบุว่า Token นี้ Subscribe topic อะไรบ้าง หรือ 2. วาง Topic ไว้บน Web local storage แล้วก็แบบ Topic มากับ Payload แล้วมาวาง Logic เองก่อนแสดง Notification ครับ ก็ถ้าเอาง่าย ก็ใช้ทางเลือกที่ 2 น่าจะสะดวกกว่านะครับ แต่ก็ต้องอย่าลืมว่า ถ้าเราไม่เก็บ Token ไว้ แล้วเราจะส่ง Push ออกมาได้ยังไง?
[update 2016–11–27] เรื่อง Subscribe topic
อันนี้ไม่แน่ใจว่าทาง Google ทำมาตั้งแต่เมื่อไร แต่ก็ดีแล้วที่มีครับ ว่าด้วยเรื่องการ Subscribe topic เนี่ย เราสามารถทำลักษณะเดียวกับ Android หรือ iOS ได้เลย คือทำผ่านชื่อ Topic ที่ต้องการได้เลย แต่ต้องยิงผ่าน REST นะ ! ก็ไม่มีอะไรมากครับ เอา jQuery มาใช้ก็ได้ครับ ในลักษณะนี้
var token = "[token from FCM]";
var topicName = "news";
var topicUrl = "https://iid.googleapis.com/iid/v1/"+token+"/rel/topics/"+topicName;
$.ajax({
url: topicUrl,
type: 'post',
data: {},
headers: {
"Content-Type": 'application/json',
"Authorization": '[project key]'
},
dataType: 'json',
success: function (data) {
console.log(“subscribe to topic: ”, data);
}
});
เพียงเท่านี้เราก็ได้ Subscribe topic ไปเรียบร้อยแล้วครับ สามารถทดลองส่ง Push แบบ Topic ที่เราสร้างไว้ได้เลย
สรุป
ถึงจะมีไม่ครบ แต่ก็ยังดีกว่าไม่มี
ก็ไม่รู้จะพูดยังไงดีกับ Web FCM เพราะว่าที่มีให้ใช้ตอนนี้มันก็ใช้ได้ดี เพียงแต่อาจจะยังไม่ได้ดีเทียบเท่าเจ้าอื่นๆ เพราะว่าเราทำอะไรผ่าน Firebase console ไม่ได้เลย ยิงก็ไม่ได้ ดู Stat ก็ไม่ได้ (จริงๆ แล้วมันก็พอดูได้ แต่ยังไม่อยากนับ เพราะไม่สมบูรณ์) ก็ต้องดูกันต่อไปนะครับ ว่า Google จะอัพเดทให้ Web FCM ดีขึ้นเทียบเท่าหรือดีกว่าเจ้าอื่นๆ มั้ย จะว่าไปแล้วก็ยังขาด Web Analytic ที่ยังไม่มารวมอยู่ใน Firebase ก็รออยู่นะครับ Google. :3
ก่อนจบก็ต้องขอขอบคุณผู้อ่านที่ไม่ว่าจะตั้งใจเข้ามา หรือจะหลงเข้ามา หากมีข้อสงสัย หรือต้องแลกเปลี่ยน แนะนำอะไร ก็ไม่ต้องเกรงใจนะครับ จัดเต็มได้เลยครับ
และเนื่องจากบทความนี้เขียนออกมาในช่วงเวลาที่ไม่เป็นที่น่ายินดี จึงขออนุญาติ อัญเชิญพระบรมราโชวาท ของพระบาทสมเด็จพระปรมินทรมหาภูมิพลอดุลยเดช ในพิธีพระราชทานแก่คณะครู นักเรียน โรงเรียนไกลกังวล วันพฤหัสบดี ที่ ๒๘ พฤษภาคม ๒๕๑๒ เพื่อให้พวกเราได้ระลึกถึงท่านครับ
… ขอให้รักเรียนทั้งหลายตั้งใจรับความรู้ที่ครูสอนเพราะโอกาสเช่นนี้หายาก ถ้าไม่เอาใจใส่พยายามเรียนก็จะหาโอกาสไม่ได้อีกเพราะเวลาที่เป็นเด็กนั้นมีน้อย จึงต้องขอให้ใช้เวลาให้ถูกต้อง สะสมความรู้ในทางหลักวิชาและความรู้ทั่วไปให้มากและดีที่สุด แล้วจะไม่ต้องเสียใจ เมื่อโตขึ้นก็จะสามารถทำหน้าที่ของตน คือทำมาหากินเลี้ยงชีวิตตน และช่วยส่วนรวมให้อยู่ได้ด้วยความก้าวหน้าและด้วยความร่มเย็น …
Source Code
https://github.com/puuga/HelloWebFCM