首页 > web前端 > js教程 > 正文

使用 JavaScript 实现推送通知:生产级方法

WBOY
发布: 2024-08-17 13:05:02
原创
467 人浏览过

Implementing Push Notifications Using JavaScript: A Production-Grade Approach

在这篇文章中,您将学习如何通过遵循生产级最佳实践使用 JavaScript 实现推送通知。最好的事情之一是我也会提供一个文件夹结构,以便您可以轻松地设置您的项目。

在现实世界的应用程序中设置推送通知需要仔细规划。我将向您展示如何在专业的 Node.js 应用程序中构建此功能。我们将介绍重要的部分,例如如何组织您的代码、确保内容安全,并确保即使您的应用程序不断增长,它也能正常运行。

首先,您需要一个库来帮助您从 Node.js 服务器发送推送通知。 web-push 库提供了用于发送通知和管理必要密钥的工具。

1. 推送通知:项目结构

首先,让我们设置项目结构以维护干净且可扩展的代码库:

/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 包

在深入实施之前,请确保您已安装以下 NPM 软件包:

  • express:一个最小且灵活的 Node.js Web 应用程序框架。
  • mongoose:用于 MongoDB 和 Node.js 的 ODM(对象数据建模)库。
  • web-push:使用 Web 推送协议发送推送通知的库。
  • dotenv:一个零依赖模块,从 .env 文件加载环境变量。
  • supertest:用于在 Node.js 中测试 HTTP 断言的库。

使用 npm 安装这些包:

bash

npm install express mongoose web-push dotenv supertest
登录后复制

2. 推送通知:项目配置

为不同环境(例如开发、生产)创建配置文件。这些文件存储特定于环境的设置。

// /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
};
登录后复制

3. 数据库建模

使用 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);
登录后复制

4. 通知服务

将处理通知的逻辑模块化到服务中。

// /services/webPushService.js
const webPush = require('web-push');
const config = require('config');

webPush.setVapidDetails(
    'mailto:example@yourdomain.org',
    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);
            });
        }
    }
};
登录后复制

5. 控制器逻辑

处理 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);
    }
};
登录后复制

6. 路由

为您的 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;
登录后复制

7. 错误处理

集中错误处理以确保应用程序不会崩溃。

// /utils/errorHandler.js
module.exports = (err, req, res, next) => {
    console.error(err.stack);
    res.status(500).send({ error: 'Something went wrong!' });
};
登录后复制

8. 应用程序入口点

初始化应用程序并连接到数据库。

// 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}`));
登录后复制

9. 安全实践

  • 环境变量:在环境变量中存储 API 密钥和数据库 URI 等敏感信息。
  • HTTPS:通过 HTTPS 为您的应用程序提供服务,以保护客户端和服务器之间的通信。
  • 内容安全策略 (CSP):实施 CSP 标头以防止跨站脚本 (XSS) 攻击。
  • 速率限制:使用express-rate-limit等中间件来保护您的API免受暴力攻击。

10. 测试

编写测试以确保您的服务在各种条件下按预期工作。

// /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');
    });
});
登录后复制

11. 部署到生产环境

  • CI/CD 管道:使用 Jenkins、GitHub Actions 或 GitLab CI 等工具设置 CI/CD 管道,以自动测试、构建和部署应用程序。
  • 容器化:对您的应用程序进行 Docker 化,以确保不同环境之间的一致性。
  • 监控:使用 Prometheus 和 Grafana 等监控工具来跟踪应用程序的运行状况和性能。

12. 缩放

  • 水平扩展:在负载均衡器后面部署服务的多个实例以处理高流量。
  • 数据库扩展:在 MongoDB 中实现分片或副本集,以实现数据库的水平扩展。

这种生产级设置可确保您的推送通知系统可扩展、安全且可维护。该代码的组织方式是为了支持轻松测试、部署和监控,遵循行业最佳实践。如果您还有任何疑问或需要具体实施细节,请随时询问!

以上是使用 JavaScript 实现推送通知:生产级方法的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!