本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言:
最近在完成大三的一个课程期末设计,独立完成做了一个博客社区,主要技术栈是:
前端:next.js + mobx + ts + antd;
后台管理系统:vue3.0 + pinia + ts + elementUI
后端:next.js + ts + 阿里云oss存储 + redis
开发的时候遇到了很多坑,后面会通过文章的方式总结自己在开发过程中踩到的坑以及一些小经验。
由于博客社区嘛,像咱们大掘金平台,是有系统消息、点赞消息啥的等信息推送,然后我也想要做一个横幅(就是系统维护中,或者是出了什么问题,想要用户感知到,所以就想做一个系统消息推送),一开始通过websocket来实现,但是next.js这个框架似乎不太支持,而是支持了一个封装websocket的socket.io这个第三方依赖。所以就使用了socket.io来进行消息推送和在线人数统计的操作,希望大家喜欢~
一、需求
先看看最终实现的效果~
说明:在后台管理系统中输入通知的主题和内容,就可以实时的在前端展示出通知给用户了
二、(后端)socket.io实现广播通信
如果要实现socket的广播通知的话,通过:
socket.broadcast.emit('notification', {
message: data
})
也就是添加了一个broadcast
// 参考medium的代码
const app = require('express')()
const server = require('http').Server(app)
const io = require('socket.io')(server, {cors:true})
const next = require('next')
const dev = process.env.NODE_ENV !== 'production';
const hostname = 'localhost';
const port = 3000;
const nextApp = next({ dev, hostname, port })
const nextHandler = nextApp.getRequestHandler()
let socketPort = 3000
io.on('connect', socket => {
socket.on('clientOnline', () => {
console.log('用户上线了')
})
socket.on('disconnect', () => {
console.log('用户关闭了')
})
// 广播通知
socket.on('notification', data => {
socket.broadcast.emit('notification', {
message: data
})
})
})
nextApp.prepare().then(() => {
app.get('*', (req, res) => {
return nextHandler(req, res)
})
app.post('*', (req, res) => {
return nextHandler(req, res)
})
server.listen(socketPort, err => {
if (err) throw err
console.log(`socket io ready on http://localhost:${port}`)
})
})
说明:上面的代码中,我们通过监听notification事件给server.js里面的socket.io服务器,而服务器接收的就是我们在后台管理系统中发送的notification事件
三、给所有用户推送系统消息(比如网站维护中)
直接上代码,之后再解释,let is go next.js的server
const app = require('express')()
const server = require('http').Server(app)
const io = require('socket.io')(server, {cors:true})
const next = require('next')
const dev = process.env.NODE_ENV !== 'production';
const hostname = 'localhost';
const port = 3000;
const nextApp = next({ dev, hostname, port })
const nextHandler = nextApp.getRequestHandler()
let socketPort = 3000
io.on('connect', socket => {
socket.on('clientOnline', () => {
console.log('用户上线了')
})
socket.on('disconnect', () => {
console.log('用户关闭了')
})
// 广播通知
socket.on('notification', data => {
socket.broadcast.emit('notification', {
message: data
})
})
})
nextApp.prepare().then(() => {
app.get('*', (req, res) => {
return nextHandler(req, res)
})
app.post('*', (req, res) => {
return nextHandler(req, res)
})
server.listen(socketPort, err => {
if (err) throw err
console.log(`socket io ready on http://localhost:${port}`)
})
})
后台系统代码(我用的是vue3写的,所以下面就是vue3中使用socket的方法了)
<template>
<div>
// 省略代码
</div>
</template>
<script lang='ts' setup>
import { ref } from 'vue'
import io from 'socket.io-client'
const socket = ref(io('http://localhost:3000'))
// ... 省略其他代码
const handleFormSuccess = (notification) => {
socket.value.emit('notification', {
title: '通知主题',
content: '通知内容'
})
}
</script>
<style lang='scss' scoped></style>
我们在后台管理系统中发送emit notification,然后在next.js的server.js建立的socket里面进行监听notification事件
server.js的关键代码:
// 广播通知
// data 为 { title: '通知主题', content: '通知内容' }
socket.on('notification', data => {
socket.broadcast.emit('notification', {
message: data
})
})
之后就是next.js的前端代码了,
在next.js的layout组件中,关于为什么要在这个组件中写代码的理由已经在第一个模块中juejin.cn/post/709946… 讲解了~
import { useEffect } from "react";
import { observer } from "mobx-react-lite"
import io from 'socket.io-client'
import { notification } from 'antd';
var socket : any
const Layout = ({ children } : any) => {
const clineOnline = () => {
socket.emit('clientOnline', '用户id')
}
const sendNotification = (title, content) => {
notification.open({
message: title,
description: content
});
}
useEffect(() => {
if (!socket) {
socket = io('http://localhost:3000')
}
document.addEventListener('visibilitychange',function(){
var isHidden = document.hidden;
if(!isHidden){
clineOnline()
}
})
// 关键代码
socket.on('notification', data => {
const { title, content } = data.message
sendNotification(title, content)
})
}, [])
return (
<div>
Layout container
</div>
)
}
export default observer(Layout)
我们在next.js前端代码中通过监听notification事件,使用antd提供的notification这个组件进行消息通知
下一节我将分享《next.js中通过socket.io结合redis来统计当前网站的在线人数》希望大家喜欢