萌新向使用指南
create-react-app
npm start
暂时不知道配置在哪。默认端口为3000,被占用时会询问是否更改端口。且默认为热启动,组件和CSS的更改都会自动更新。
对于stylus,stylus-loader可以使.styl文件被直接使用,未尝试过。也可以引入CSS文件,然后使用stylus -w style.styl -o style.css来自动编译成CSS。
npm run build
生成的html文件不能直接打开,需要配置服务器,并将静态目录设置为生成的build文件夹。若要直接打开查看,只需将html文件中所有资源引用的地址前加上.,变成./xxx即可。(可通过配置package.json直接生成这样的路径,但并不推荐,详见这里)
socket.io
服务端
可与express一起使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16const app = require('express')()
const server = require('http').createServer(app)
const io = require('socket.io')(server)
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html')
})
io.on('connection', function(socket) {
console.log('a user connected')
})
// 只能使用server进行监听
server.listen(3000, function() {
console.log('listening on *:3000')
})
注意:此时server.listen()中监听的端口为websocket的端口。且必须使用server监听端口,若使用app监听端口,只能获取到网页文件而不能进行websocket连接。
消息推送(emit)
emit的语法:https://socket.io/docs/server-api/#socket-emit-eventname-args-ackemit多种推送方式的相关说明不在API中,而是在下面的页面中做介绍:
https://socket.io/docs/rooms-and-namespaces/
https://socket.io/docs/emit-cheatsheet/
语法:socket.emit(eventName[, ...args][, ack])
eventName为推送的标志;args为任意多的推送数据;ack为一个函数,可选,在客户端应答时可被调用(可确认客户端是否接受到讯息),详见官网例子。
io.emit
io.emit与io.sockets.emit等价。将消息推送至所有连接到的客户端。(准确地讲是连接到默认命名空间default namespace,即/下的所有客户端。通过io.connection连接的,都会连接到/。namespace很好理解,不做介绍,需要可看官网)
socket.emit
socket.emit中的socket为io.on('connection', (socket) => {...})中回调的参数。此为只向该客户端发送消息。
更多推送方式可看官网,简短易懂。
客户端
首先需要引入js文件1
2
3
4
5
6
7
8// 直接在静态html文件中写入,无其他要求
<script src="/socket.io/socket.io.js"></script>
// 未遇见,可能Vue,Angular需要使用
const io = require('socket.io-client')
// 在React中使用
import io from 'socket.io-client'
引入后需要const socket = io()来进行连接。io为所引入的js文件暴露的函数。io()可传入一个连接的url(string)。不传入则默认为window.location。更多见文档。
- 接收服务端推送:
socket.on(eventName, ...args [, fn])
其中eventName为服务端推送对应标志;...args为推送数据,与服务端对应;fn为回调函数,可选。
- 推送数据至服务端:
socket.emit()。语法与服务端的推送一致
注意:客户端和服务端都能进行推送和接收,且语法一致
create-react-app + socket.io
开发阶段
使用create-react-app新建项目后,在命令行中进入文件夹,安装socket.io:npm i --save socket.io
对于React,一般可在App.js中引入socket.io的js文件,此时会自动连接:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34import React, { Component } from "react"
// 此处引入
import io from "socket.io-client"
class App extends Component {
constructor() {
super()
this.state = {
msg : false,
// 此处连接到本地的`3001`端口
endpoint : "http://127.0.0.1:3001"
}
}
componentDidMount() {
const { endpoint } = this.state
const socket = io(endpoint)
socket.on("Msg", data => this.setState({ msg : data }))
}
render() {
const { msg } = this.state
return (
<div>
{msg ?
<p>{msg}</p> :
<p>Loading...</p>}
</div>
)
}
}
export default App
若有需要手动连接/断开,可如下操作:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26constructor() {
super()
this.state = {
socket : io('localhost:3001', {
autoConnect: false // 设置为不自动连接
}),
msg : false,
}
this.state.socket.on('Msg', (msg) => {
this.updata(msg)
})
}
updata(msg) {
this.setState({msg : msg})
}
componentWillMount() {
// 连接
this.state.socket.open()
}
componentWillUnmount() {
// 断开
this.state.socket.close()
}
对于服务端,开发阶段可以直接在项目根目录放入server.js文件,用来提供推送(可不使用express)1
2
3
4
5
6
7
8
9
10
11
12
13
14const server = require('http').createServer()
const io = require('socket.io')(server)
const port = 3001 // 端口要对应
let emitData = 'emit test'
io.on('connection', (socket) => {
socket.emit('Msg', emitData)
})
server.listen(port, () => {
console.log("Running...")
});
进行测试时只需启动server.js文件并使用npm start即可。
部署
正式部署时,一个端口可同时用来进行网页访问和websocket连接。若不想再单独开启一个端口,可将React中io()传入的url参数清除。
使用npm run build将React项目生成静态文件,然后将build目录复制到服务器项目下,同时将静态目录设置为build文件夹。如express:app.use(express.static(__dirname + '/build'))