forked from vercel/next.js
/
use-websocket.ts
65 lines (55 loc) · 1.77 KB
/
use-websocket.ts
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import { useCallback, useContext, useEffect, useRef } from 'react'
import { GlobalLayoutRouterContext } from '../../../../../shared/lib/app-router-context'
import { getSocketProtocol } from './get-socket-protocol'
export function useWebsocket(assetPrefix: string) {
const webSocketRef = useRef<WebSocket>()
useEffect(() => {
if (webSocketRef.current) {
return
}
const { hostname, port } = window.location
const protocol = getSocketProtocol(assetPrefix)
const normalizedAssetPrefix = assetPrefix.replace(/^\/+/, '')
let url = `${protocol}://${hostname}:${port}${
normalizedAssetPrefix ? `/${normalizedAssetPrefix}` : ''
}`
if (normalizedAssetPrefix.startsWith('http')) {
url = `${protocol}://${normalizedAssetPrefix.split('://')[1]}`
}
webSocketRef.current = new window.WebSocket(`${url}/_next/webpack-hmr`)
}, [assetPrefix])
return webSocketRef
}
export function useSendMessage(webSocketRef: ReturnType<typeof useWebsocket>) {
const sendMessage = useCallback(
(data) => {
const socket = webSocketRef.current
if (!socket || socket.readyState !== socket.OPEN) {
return
}
return socket.send(data)
},
[webSocketRef]
)
return sendMessage
}
export function useWebsocketPing(
websocketRef: ReturnType<typeof useWebsocket>
) {
const sendMessage = useSendMessage(websocketRef)
const { tree } = useContext(GlobalLayoutRouterContext)
useEffect(() => {
// Taken from on-demand-entries-client.js
// TODO-APP: check 404 case
const interval = setInterval(() => {
sendMessage(
JSON.stringify({
event: 'ping',
tree,
appDirRoute: true,
})
)
}, 2500)
return () => clearInterval(interval)
}, [tree, sendMessage])
}