اپلیکیشنهای پیشرونده وب حاوی مجموعهای از تکنولوژیها، مفاهیم طراحی و Web APIها هستند. آنها با به کارگیری این موارد سعی در ایجاد یک اپلیکیشن با تجربهای مشابه اپلیکیشنهای موبایل در سطح وب را دارند. در این آموزش ما قصد داریم به شما شیوه ساخت وب اپلیکیشنهای پیشرونده یا PWA را با استفاده از Firebase آموزش دهیم.
نکته: قبل از خواندن ادامه این مطلب نیاز است که دانش پایه و کافی از مفاهیم Firebase و کار با آن را داشته باشید.
ادغام سازی Node-FCM در سرور NodeJS
در ادامه با ادغام کردن FCM یا Firebase Cloud Messaging با اپلیکیشنهای نودجیاس همراه خواهیم بود. این پروسه آسان و به صورت سریع انجام میشود.
چگونه این کار را انجام دهیم؟
بیایید قبل از هر چیزی از اینکه محیط توسعهمان برای پروژه آماده است مطمئن شویم، بنابراین بیایید چند مورد از مستقلات را نصب کنیم.
۱. ترمینال را باز کرده و دستور زیر را اجرا کنید:
npm install fcm-push --save
با استفاده از این دستور ما کتابخانه fcm-push را به صورت محلی دانلود و نصب کردهایم. اگر این دستور اجرا شود، به ما کمک میکند که بتوانیم پروسه ارسال رویدادها به کاربران را انجام دهیم.
اکوسیستم نودجیاس دارای یک مدیریت پکیج به نام NPM است. بنابراین برای اینکه آن را در اختیار داشته باشید نیاز است که نودجیاس را روی سیستم خود نصب کرده و براساس سیستمعاملتان کارهای پیکربندی را انجام دهید.
۲. حال ما کتابخانه مورد نظرمان را به صورت محلی و درست نصب کردیم، به این جهت که قصد ادغام آن با اپلیکیشنمان را داشته باشیم یک خط کد دیگر نیاز داریم. در داخل پروژه توسعه محلی خود یک فایل جدید ایجاد کنید و کدهای زیر را در آن قرار دهید:
const FCM = require('fcm-push');
تبریک! ما به نحوی کار را به اتمام رساندیم. در قسمت بعدی ما شیوه مدیریت مسیرمان از طریق پروسه ارسال را پیادهسازی میکنیم و خواهیم دید که چگونه میتوانیم یک رویداد وب را به کاربران ارسال کنیم.
پیادهسازی سرویس ورکرها
سرویس ورکرها در واقع قسمت گم شدهای از دنیای وب بودند. آنها به ما قابلیت پاسخگویی به اپلیکیشنها را در هر مقطع از اپلیکیشن وب میدهند. برای مثال یک پیام نوتیفیکشن یا یک وضعیت بدون اینترنت (آفلاین) و... .در این قسمت شیوه ادغامسازی سرویس ورکرها ما اپلیکیشنمان را خواهیم گفت.
فایلهای سرویس ورکرها مبتنی بر رویداد هستند بنابراین هر اتفاقی که در آنها میافتد مبتنی بر رویداد است. از آن جایی که جاوااسکریپت هستند میتوانیم آنها را به هر رویدادی متصل کنیم. برای انجام چنین کاری، ما نیاز به یک منطق منحصر به فرد داریم که با دنبال کردن این منطق رویداد به صورت پیشفرض خود راهش را ادامه میدهد.
چگونه این کار را انجام دهیم؟
سرویس ورکرها در مرورگر زندگی میکنند بنابراین قرار دادن آنها در باندل فرانتاند خود بهترین راهکار است.
۱. موضوع بالا را در ذهن داشته باشید، بیایید یک فایلهایی با نام firebase-messaging-sw.js و manifest.json را ایجاد کنیم. فایل جاوااسکریپت فایل مربوط به سرویس ورکر ما خواهد بود و تمام موارد workload را در خود میزبانی میکند. همچنین فایل json یک فایل پیکربندی متاداده ساده برایمان خواهد بود.
۲. بعد از این مطمئن شوید که یک فایل app.js را نیز ایجاد میکنید. این فایل نقطه شروع ما برای Authorization و تجربه کاربری سفارشی خواهد بود. ما در رابطه با اهمیت هر کدام از این فایلها به صورت منحصر به فرد در ادامه توضیحاتی میدهیم، اما برای حال ما به firebase-messaging-sw.js برگشته و کدهای زیر را مینویسیم:
ابتدای کار اسکریپتهای مورد نیاز را import میکنیم:
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js');
سپس Firebase را کانفیگ میکنیم:
var config = {
apiKey: "",
authDomain: "",
databaseURL: "",
storageBucket: "",
messagingSenderId: ""
};
اپلیکیشن را پایهگذاری میکنیم (مقدار اولیه):
firebase.initializeApp(config);
شیء Messaging را پایهگذاری میکنیم؛
const messaging = firebase.messaging();
رویداد SW:
self.addEventListener('install', function(event) {
console.log("Install Step, let's cache some files =D");
});
فعالسازی رویداد SW:
self.addEventListener('activate', function(event) {
console.log('Activated!', event);
});
در داخل هر فایل سرویس ورکر، پیادهسازی رویداد همواره مرحله ابتدایی ماجرا است. در داخل این رویداد میتوانیم به هر رویدادی که میخواهیم منطق کاری را اضافه و سفارشی نماییم. این منطق کاری میتواند هر چیزی باشد.
۳. در داخل فایل metadata که فایل manifest.json خواهد بود، کدهای زیر را وارد کنید:
{
"name": "Firebase Cookbook",
"gcm_sender_id": "103953800507"
}
چگونه کار میکند؟
برای انجام این قسمت از کار به صورت زیر عمل میکنیم:
- با استفاده از importscript اسکریپتهای مورد نظر را وارد کنید. بعد از آن شیء کانفیگ Firebase را معرفی میکنیم.
- اپلیکیشن Firebase را با فایل کانفیگ پایهگذاری و مقداردهی اولیه میکنید.
- یک رفرنس جدید از کتابخانه firebase.messaging ایجاد میکنیم. این کار باعث میشود که همیشه به یاد داشته باشیم که در Firebase همه چیز با رفرنس شروع میشود.
- در نهایت ما رویدادها را فعال کرده و متنهایی را در قسمت دیباگر مرورگر قرار میدهیم.
همچنین در فایل manifest.json متادادههای زیر را وارد میکنیم:
- نام اپلیکیشن (اختیاری)
- gcm_sender_id با یک مقدار. در نظر داشته باشید که این مقدار در پروژههای جدیدی که در آينده ایجاد خواهید کرد تغییر نخواهد کرد. بهتر است در رابطه با این مقدار دقت بالایی داشته باشید.
پیادهسازی ثبت ارسال/دریافت با استفاده از Socket.IO
تا به اینجای کار ما سرور FCM خود را ادغام کردیم و سرویس ورکر را برای میزبانی کردن منطق سفارشیمان آماده نمودیم. همانطور که اشاره کردیم ما قصد داریم که رویدادهایی را بدون اینکه کاربران از اپلیکیشن استفاده کنند از طریق مرورگر برای آنها ارسال نماییم. بعد از آن این رویدادها توانایی ترکیب با هر اپلیکیشن دیگری را خواهند داشت. پس بیایید در اولین رویکردی که پیش رو داریم از Socket.io استفاده کنیم.
به این جهت که سرور FCM را از کاربران آگاه کنیم، از registration_id مربوط به مرورگرها استفاده میکنیم. این مورد یک توکن منحصر به فرد است که برای تمام مرورگرها وجود دارد و کلاینتهای ما را براساس مرورگر و نیازهایشان نشان داده و برای سرور FCM ارسال میکند.
هر مرورگر توکن registration_id خود را تولید میکند. بنابراین اگر کاربری اولین تعاملش با سرور را از طریق مرورگری مانند کروم انجام دهد بعد از آن قابلیت دریافت و ارسال نوتیفیکشن از طریق فایرفاکس را نخواهد داشت. بعد از آن نیاز است که یکبار دیگر توکن جدید را دریافت کنند.
چگونه این کار را انجام دهیم؟
۱. در مرحله اول نیاز است که به پروژه نودجیاس که در قسمتهای ابتدایی این مقاله ایجاد کردیم برگردیم. در مرحله اول باید موارد مربوط به Socket.io و express را نصب کنیم:
npm install express socket.io --save
۲. Socket.io مبتنی بر رویداد است و به ما اجازه میدهد که برای هر چیزی رویدادهای سفارشی را ایجاد کنیم. همچنین ما ExpressJs را برای پیکربندی Socket.io در جهت ایجاد سرور نصب کردهایم.
۳. حال نیاز است که با استفاده از express سرور socket.io را پیکربندی کنیم. در این حالت مانند کدهای زیر عمل نمایید:
const express = require('express');
const app = express();
app.io = require('socket.io')();
// [*] Configuring our static files.
app.use(express.static('public/'));
// [*] Configuring Routes.
app.get('/', (req, res) => {
res.sendFile(__dirname + '/public/index.html');
});
// [*] Configuring our Socket Connection.
app.io.on('connection', socket => {
console.log('Huston ! we have a new connection
...');
})
در این کدها ما به صورت زیر عمل کردیم:
- experss را import کرده و یک اپلیکیشن express جدید ایجاد نمودهایم.
- با استفاده پکیج socket.io یک زیرشیء درست کردهایم. این ادغام باعث میشود که اپلیکیشن بتواند از هر دو پکیج پشتیبانی کند.
- ما پوشه عمومی را که در آن فایلهای HTML/CSS و... وجود دارد را به عنوان پوشه فایلهای ایستا معرفی کردهایم.
- یک ارتباط جدید را ایجاد کردهایم که هر وقت کاربر جدیدی وارد شد، برقرار میشود.
- وقتی یک ارتباط جدید برقرار میشود ما یک پیام را در قسمت کنسول چاپ میکنیم.
۴. حال نیاز است که قسمت فرانتاند را پیکربندی کنیم. برای اینکار در فایل html اصلی خط کد زیر را به انتهای تگ head اضافه کنید:
<script src="/socket.io/socket.io.js"></script>
۵. فایل Socket.io بعد از این اپلیکیشن اجرا شد، ایجاد میشود. در نهایت قبل از اینکه تگ body را ببندید، کد زیر را در آخرین خط آن اضافه کنید:
<script>
var socket = io.connect('localhost:3000');
</script>
در این کد ما قسمت بکاند و فرانتاند را به همدیگر متصل کردیم. این اتصال از طریق پورت ۳۰۰۰ انجام میشود.
۶. حال به فایل app.js که در مراحل قبلی ایجاد کردیم، بازگردید و کدهای زیر را در آن قرار دهید:
//[*] Importing Firebase Needed Dependencies
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/3.5.2/firebase-messaging.js');
Copy
// [*] Firebase Configurations
var config = {
apiKey: "",
authDomain: "",
databaseURL: "",
storageBucket: "",
messagingSenderId: ""
};
//[*] Initializing our Firebase Application.
firebase.initializeApp(config);
// [*] Initializing the Firebase Messaging Object.
const messaging = firebase.messaging();
همه چیز عالی است. یادتان نرود که برای کارکرد درست باید app.js را داخل index.html فراخوانی کنید. حال باید شیوه دریافت registration_id که در قبل توضیح دادیم را پیادهسازی کنیم:
۱. همانطور که قبلا اشاره کردم توکن مربوط به registration برای هر مرورگر منحصر به فرد است. با این حال برای اینکه آن را دریافت کنید باید بدانید که این توکن ممکن است با مشکلات امنیتی برخورد کند. برای اینکه این توکن در دست هر کسی نیافتد، در همه جا قابل دسترس نیست بنابراین شما نیاز به مجوز کاربری از مرورگر دارید. از آنجایی که میتوانید از این توکن در اپلیکیشنهای خاص استفاده کنید، بنابراین بیاید شیوه انجام دادن آن را مشاهده کنیم.
از آنجایی که اگر یک هکر به توکن registration_id دسترسی پیدا کند میتواند پیامهای اسپم و اشتباهی را برای کاربران ارسال نماید بنابراین باید با آن به عنوان یک خطر امنیتی رفتار میشود. بنابراین امن نگه داشتن و محافظت کردن از این توکنها باید در وهله اول باشد.
۲. حال در داخل فایل app.js در زیر رفرنس مربوط به Firebase Messaging کدهای زیر را قرار دهید:
messaging.requestPermission()
.then(() => {
console.log("We have permission !");
return messaging.getToken();
})
.then((token) => {
console.log(token);
socket.emit("new_user", token);
})
.catch(function(err) {
console.log("Huston we have a problem !",err);
});
حال ما از طریق socket.io توکن را ارسال کردیم، برای اینکه بتوانیم دادههایی را از آن دریافت نماییم میتوانیم به سادگی رویدادی را فراخوانی کنیم. به این امید که قسمت بکاند بتواند دادههایی را برگشت دهد. در زیر در ارتباط با دریافت توکن registration اطلاعات بیشتری کسب میکنیم:
۱. به فایل app.js برگشته و در داخل رویداد ارتباط کدهای زیر را قرار دهید:
socket.on('new_user', (endpoint) => {
console.log(endpoint);
//TODO : Add endpoint aka.registration_token, to
secure place.
});
۲. منطق کاری socket.io براساس کدهای زیر به خوبی نمایش داده میشود:
// [*] Configuring our Socket Connection.
app.io.on('connection', socket => {
console.log('Huston ! we have a new connection
...');
socket.on('new_user', (endpoint) => {
console.log(endpoint);
//TODO : Add endpoint aka.registration_token, to
secure place.
});
});
حال ما ارتباط دوطرفهمان را برقرار کردیم. بیایید registration_token را دریافت و در جایی امن برای استفاده در آينده ذخیره کنیم.
در این قسمت قصد دارم در رابطه با شیوه دریافت مقدار registration_token که در مرحله قبل انجام دادیم کمی توضیحات بیشتری را ارائه دهم:
- ما از رفرنس Firebase Messaging که قبلا ایجاد کردیم و با تابع requestPermission() اجرا نمودیم استفاده میکنیم.
- حال با در نظر گرفتن این شرایط اگر صفحه را در مرورگر خود دریافت کنید با چنین شکلی مواجه میشوید:
- اگر به نوتیفیکشنها اجازه (Allow) بدهیم، تابع اجرا شده و مقدار registration_token از طریق themessaging.getToken() برگشت داده میشود.
- بعد از آن ما توکن را به یک سوکت ارسال کرده و آن را از طریق یک رویداد با نام new_user برگشت میدهیم.
پیادهسازی ثبت ارسال/دریافت با استفاده از درخواستهای post
براساس یک راه متفاوت بیایید حالتی را که بجای استفاده از socket.io از درخواستهای post استفاده میکنیم را توضیح دهم. در این حالت ما از REST API استفاده میکنیم. این API درخواستها را برایمان مدیریت میکند در همین عین مقادیر ذخیره شده registration_token نیز در یک جای امن ذخیره میشود. خب بیایید با روش پیکربندی این حالت آشنا شویم.
۱. ابتدای کار باید شروع به نوشتن REST API بکنیم. این کار را با ایجاد یک express post endpoint انجام میدهیم. اما قبل از آن باید مواردی که نیاز داریم را نصب کنیم:
npm install express body-parser --save
حال بیایید اپلیکیشن مورد نیازمان را پیکربندی کنیم. در داخل فایل app.js کدهای زیر را قرار دهید:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
// [*] Configuring Body Parser.
app.use(bodyParser.json());
// [*] Configuring Routes.
app.post('/regtoken', (req, res) => {
let reg_token =req.body.regtoken;
console.log(reg_token);
//TODO : Create magic while saving this token in
secure place.
});
۳. حال برای ارسال توکن به سمت کاربر میتوانید از یک درخواست HTTP استفاده کنید. اما برای اینکه همه چیز اطمینان بیشتری داشته باشید از API محلی دریافت مرورگر استفاده میکنم.
۴. برای دریافت مقدار registration_token و ارسال آن به سرور با استفاده از درخواست post و امکانات محلی مرورگر باید به صورت زیر عمل کنیم:
messaging.requestPermission()
.then(() => {
console.log("We have permission !");
return messaging.getToken();
})
.then((token) => {
console.log(token);
//[*] Sending the token
fetch("http://localhost:3000/regtoken", {
method: "POST"
}).then((resp) => {
//[*] Handle Server Response.
})
.catch(function(err) {
//[*] Handle Server Error.
})
})
.catch(function(err) {
console.log("Huston we have a problem !", err);
});
در این کد ما از رفرنس Firebase messaging استفاده کردیم. بعد از آن براساس مراحلی که قبلا طی کردهایم، با اجرای مرورگر با مجوز دسترسی به درخواست رویداد مواجه میشویم:
اگر Allow صادر شود تابع اجرا شده و مقدار registration_token از messaging.getToken() برگشت داده میشود. بعد از آن ما API دریافت که یک URL دریافت کرده را مورد استفاده قرار میدهیم.
دریافت پیامهای رویداد از طریق وب
در این مرحله از کار قصد داریم پیام را از طریق یک سرور در یک پیام رویداد وب دریافت کنیم. استفاده از این شیوه میتواند اطمینان کاری خوبی را به شما بدهد.
برای انجام این کار کدهای زیر را به firebase-messaging-sw.js اضافه کنید:
// [*] Special object let us handle our Background Push
Notifications
messaging.setBackgroundMessageHandler(function(payload)
{ return
self.registration.showNotification(payload.data.title,
body: payload.data.body);
});
حال قسمت فرانت اند را برای دریافت پیام آماده کردهایم. بیایید پیامها را از طریق سرور ارسال کنیم. برای این کار به صورت زیر عمل نمایید:
var fcm = new FCM('FCM_CODE>');
var message = {
to: data.endpoint, // required fill with device
token or topics
notification: {
title: data.payload.title,
body: data.payload.body
}
};
fcm.send(message)
.then(function(response) {
console.log("Successfully sent with response: ",
response);
})
.catch(function(err) {
console.log("Something has gone wrong!");
console.error(err);
})
});
مهمترین قسمت ماجرا FCM_CODE است. میتوانید آن را از قسمت Firebase console دریافت کنید:
بعد از آن به قسمت CLOUD MESSAGING رفته و Server Key را از آنجا کپی کنید:
کارمان تمام شد. حال میتوانید به اپلیکیشنتان مراجعه کرده و از کارایی جدید آن لذت ببرید.
این مطلب برداشتی از کتاب «Firebase Cookbook» بوده، بنابراین برای مطالعه بیشتر در این رابطه میتوانید به این مطلب مراجعه کنید.
دیدگاه و پرسش
در حال دریافت نظرات از سرور، لطفا منتظر بمانید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید