В этом посте вы узнаете, как реализовать push-уведомления с помощью JavaScript, следуя передовым практикам производственного уровня. Самое приятное то, что я также предоставлю структуру папок, чтобы вы могли легко настроить свой проект.
Настройка push-уведомлений в реальном приложении требует тщательного планирования. Я покажу вам, как реализовать эту функцию в профессиональном приложении Node.js. Мы рассмотрим важные части, например, как организовать ваш код, обеспечить его безопасность и убедиться, что он работает хорошо даже по мере роста вашего приложения.
Для начала вам понадобится библиотека, которая поможет отправлять push-уведомления с вашего сервера Node.js. Библиотека web-push предоставляет инструменты для отправки уведомлений и управления необходимыми ключами.
Во-первых, давайте настроим структуру проекта для поддержания чистой и масштабируемой базы кода:
/notification-service ├── /config │ ├── default.js │ └── production.js ├── /controllers │ └── notificationController.js ├── /models │ └── user.js ├── /routes │ └── notificationRoutes.js ├── /services │ ├── notificationService.js │ ├── subscriptionService.js │ └── webPushService.js ├── /utils │ └── errorHandler.js ├── /tests │ └── notification.test.js ├── app.js ├── package.json ├── .env └── README.md
Прежде чем приступить к реализации, убедитесь, что у вас установлены следующие пакеты NPM:
bash npm install express mongoose web-push dotenv supertest
Создавайте файлы конфигурации для различных сред (например, разработки, производства). В этих файлах хранятся настройки, специфичные для среды.
// /config/default.js module.exports = { server: { port: 3000, env: 'development' }, pushNotifications: { publicVapidKey: process.env.VAPID_PUBLIC_KEY, privateVapidKey: process.env.VAPID_PRIVATE_KEY, gcmApiKey: process.env.GCM_API_KEY }, db: { uri: process.env.MONGO_URI } };
// /config/production.js module.exports = { server: { port: process.env.PORT || 3000, env: 'production' }, // Same structure as default, with production-specific values };
Используйте Mongoose, чтобы определить схему пользователя и подписки на уведомления.
// /models/user.js const mongoose = require('mongoose'); const subscriptionSchema = new mongoose.Schema({ endpoint: String, keys: { p256dh: String, auth: String } }); const userSchema = new mongoose.Schema({ email: { type: String, required: true, unique: true }, subscriptions: [subscriptionSchema], preferences: { pushNotifications: { type: Boolean, default: true } } }); module.exports = mongoose.model('User', userSchema);
Модулизируйте логику обработки уведомлений в сервисы.
// /services/webPushService.js const webPush = require('web-push'); const config = require('config'); webPush.setVapidDetails( 'mailto:[email protected]', config.get('pushNotifications.publicVapidKey'), config.get('pushNotifications.privateVapidKey') ); module.exports = { sendNotification: async (subscription, payload) => { try { await webPush.sendNotification(subscription, JSON.stringify(payload)); } catch (error) { console.error('Error sending notification', error); } } };
// /services/notificationService.js const User = require('../models/user'); const webPushService = require('./webPushService'); module.exports = { sendPushNotifications: async (userId, payload) => { const user = await User.findById(userId); if (user && user.preferences.pushNotifications) { user.subscriptions.forEach(subscription => { webPushService.sendNotification(subscription, payload); }); } } };
Обработка маршрутов API и интеграция сервисов.
// /controllers/notificationController.js const notificationService = require('../services/notificationService'); exports.sendNotification = async (req, res, next) => { try { const { userId, title, body } = req.body; const payload = { title, body }; await notificationService.sendPushNotifications(userId, payload); res.status(200).json({ message: 'Notification sent successfully' }); } catch (error) { next(error); } };
Настройте маршруты для вашего API.
// /routes/notificationRoutes.js const express = require('express'); const router = express.Router(); const notificationController = require('../controllers/notificationController'); router.post('/send', notificationController.sendNotification); module.exports = router;
Централизуйте обработку ошибок, чтобы приложение не вылетало.
// /utils/errorHandler.js module.exports = (err, req, res, next) => { console.error(err.stack); res.status(500).send({ error: 'Something went wrong!' }); };
Инициализируйте приложение и подключитесь к базе данных.
// app.js const express = require('express'); const mongoose = require('mongoose'); const config = require('config'); const notificationRoutes = require('./routes/notificationRoutes'); const errorHandler = require('./utils/errorHandler'); const app = express(); app.use(express.json()); app.use('/api/notifications', notificationRoutes); app.use(errorHandler); mongoose.connect(config.get('db.uri'), { useNewUrlParser: true, useUnifiedTopology: true }) .then(() => console.log('MongoDB connected...')) .catch(err => console.error('MongoDB connection error:', err)); const PORT = config.get('server.port'); app.listen(PORT, () => console.log(`Server running in ${config.get('server.env')} mode on port ${PORT}`));
Напишите тесты, чтобы убедиться, что ваш сервис работает должным образом в различных условиях.
// /tests/notification.test.js const request = require('supertest'); const app = require('../app'); describe('Notification API', () => { it('should send a notification', async () => { const res = await request(app) .post('/api/notifications/send') .send({ userId: 'someUserId', title: 'Test', body: 'This is a test' }); expect(res.statusCode).toEqual(200); expect(res.body.message).toBe('Notification sent successfully'); }); });
Эта настройка промышленного уровня гарантирует, что ваша система push-уведомлений будет масштабируемой, безопасной и удобной в обслуживании. Код организован таким образом, чтобы обеспечить простоту тестирования, развертывания и мониторинга в соответствии с лучшими отраслевыми практиками. Если у вас есть дополнительные вопросы или вам нужны конкретные подробности реализации, не стесняйтесь спрашивать!
Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.
Copyright© 2022 湘ICP备2022001581号-3