next
Version:
The React Framework
238 lines (236 loc) • 9.78 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
0 && (module.exports = {
createProcessTurbopackMessage: null,
createWebSocket: null,
useWebSocketPing: null
});
function _export(target, all) {
for(var name in all)Object.defineProperty(target, name, {
enumerable: true,
get: all[name]
});
}
_export(exports, {
createProcessTurbopackMessage: function() {
return createProcessTurbopackMessage;
},
createWebSocket: function() {
return createWebSocket;
},
useWebSocketPing: function() {
return useWebSocketPing;
}
});
const _react = require("react");
const _approutercontextsharedruntime = require("../../../../shared/lib/app-router-context.shared-runtime");
const _getsocketurl = require("../get-socket-url");
const _hotreloadertypes = require("../../../../server/dev/hot-reloader-types");
const _shared = require("../shared");
const _hotreloaderapp = require("./hot-reloader-app");
const _forwardlogs = require("../../../../next-devtools/userspace/app/forward-logs");
const _invarianterror = require("../../../../shared/lib/invariant-error");
const _constants = require("../../../../lib/constants");
let reconnections = 0;
let reloading = false;
let serverSessionId = null;
let mostRecentCompilationHash = null;
function createWebSocket(assetPrefix, staticIndicatorState) {
if (!self.__next_r) {
throw Object.defineProperty(new _invarianterror.InvariantError(`Expected a request ID to be defined for the document via self.__next_r.`), "__NEXT_ERROR_CODE", {
value: "E806",
enumerable: false,
configurable: true
});
}
let webSocket;
let timer;
const sendMessage = (data)=>{
if (webSocket && webSocket.readyState === webSocket.OPEN) {
webSocket.send(data);
}
};
const processTurbopackMessage = createProcessTurbopackMessage(sendMessage);
function init() {
if (webSocket) {
webSocket.close();
}
const newWebSocket = new window.WebSocket(`${(0, _getsocketurl.getSocketUrl)(assetPrefix)}/_next/webpack-hmr?id=${self.__next_r}`);
newWebSocket.binaryType = 'arraybuffer';
function handleOnline() {
_forwardlogs.logQueue.onSocketReady(newWebSocket);
reconnections = 0;
window.console.log('[HMR] connected');
}
function handleMessage(event) {
// While the page is reloading, don't respond to any more messages.
if (reloading) {
return;
}
try {
const message = event.data instanceof ArrayBuffer ? parseBinaryMessage(event.data) : JSON.parse(event.data);
// Check for server restart in Turbopack mode
if (message.type === _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.TURBOPACK_CONNECTED) {
if (serverSessionId !== null && serverSessionId !== message.data.sessionId) {
// Either the server's session id has changed and it's a new server, or
// it's been too long since we disconnected and we should reload the page.
window.location.reload();
reloading = true;
return;
}
serverSessionId = message.data.sessionId;
}
// Track webpack compilation hash for server restart detection
if (message.type === _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.SYNC && 'hash' in message) {
// If we had previously reconnected and the hash changed, the server may have restarted
if (mostRecentCompilationHash !== null && mostRecentCompilationHash !== message.hash) {
window.location.reload();
reloading = true;
return;
}
mostRecentCompilationHash = message.hash;
}
(0, _hotreloaderapp.processMessage)(message, sendMessage, processTurbopackMessage, staticIndicatorState);
} catch (err) {
(0, _shared.reportInvalidHmrMessage)(event, err);
}
}
function handleDisconnect() {
newWebSocket.onerror = null;
newWebSocket.onclose = null;
newWebSocket.close();
reconnections++;
// After 25 reconnects we'll want to reload the page as it indicates the dev server is no longer running.
if (reconnections > _constants.WEB_SOCKET_MAX_RECONNECTIONS) {
reloading = true;
window.location.reload();
return;
}
clearTimeout(timer);
// Try again after 5 seconds
timer = setTimeout(init, reconnections > 5 ? 5000 : 1000);
}
newWebSocket.onopen = handleOnline;
newWebSocket.onerror = handleDisconnect;
newWebSocket.onclose = handleDisconnect;
newWebSocket.onmessage = handleMessage;
webSocket = newWebSocket;
return newWebSocket;
}
return init();
}
function createProcessTurbopackMessage(sendMessage) {
if (!process.env.TURBOPACK) {
return ()=>{};
}
let queue = [];
let callback;
const processTurbopackMessage = (msg)=>{
if (callback) {
callback(msg);
} else {
queue.push(msg);
}
};
import(// @ts-expect-error requires "moduleResolution": "node16" in tsconfig.json and not .ts extension
'@vercel/turbopack-ecmascript-runtime/browser/dev/hmr-client/hmr-client.ts').then(({ connect })=>{
connect({
addMessageListener (cb) {
callback = cb;
// Replay all Turbopack messages before we were able to establish the HMR client.
for (const msg of queue){
cb(msg);
}
queue.length = 0;
},
sendMessage,
onUpdateError: (err)=>(0, _hotreloaderapp.performFullReload)(err, sendMessage)
});
});
return processTurbopackMessage;
}
function useWebSocketPing(webSocket) {
const { tree } = (0, _react.useContext)(_approutercontextsharedruntime.GlobalLayoutRouterContext);
(0, _react.useEffect)(()=>{
if (!webSocket) {
throw Object.defineProperty(new _invarianterror.InvariantError('Expected webSocket to be defined in dev mode.'), "__NEXT_ERROR_CODE", {
value: "E785",
enumerable: false,
configurable: true
});
}
// Never send pings when using Turbopack as it's not used.
// Pings were originally used to keep track of active routes in on-demand-entries with webpack.
if (process.env.TURBOPACK) {
return;
}
// Taken from on-demand-entries-client.js
const interval = setInterval(()=>{
if (webSocket.readyState === webSocket.OPEN) {
webSocket.send(JSON.stringify({
event: 'ping',
tree,
appDirRoute: true
}));
}
}, 2500);
return ()=>clearInterval(interval);
}, [
tree,
webSocket
]);
}
const textDecoder = new TextDecoder();
function parseBinaryMessage(data) {
assertByteLength(data, 1);
const view = new DataView(data);
const messageType = view.getUint8(0);
switch(messageType){
case _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER:
{
const serializedErrors = new Uint8Array(data, 1);
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.ERRORS_TO_SHOW_IN_BROWSER,
serializedErrors
};
}
case _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK:
{
assertByteLength(data, 2);
const requestIdLength = view.getUint8(1);
assertByteLength(data, 2 + requestIdLength);
const requestId = textDecoder.decode(new Uint8Array(data, 2, requestIdLength));
const chunk = data.byteLength > 2 + requestIdLength ? new Uint8Array(data, 2 + requestIdLength) : null;
return {
type: _hotreloadertypes.HMR_MESSAGE_SENT_TO_BROWSER.REACT_DEBUG_CHUNK,
requestId,
chunk
};
}
default:
{
throw Object.defineProperty(new _invarianterror.InvariantError(`Invalid binary HMR message of type ${messageType}`), "__NEXT_ERROR_CODE", {
value: "E809",
enumerable: false,
configurable: true
});
}
}
}
function assertByteLength(data, expectedLength) {
if (data.byteLength < expectedLength) {
throw Object.defineProperty(new _invarianterror.InvariantError(`Invalid binary HMR message: insufficient data (expected ${expectedLength} bytes, got ${data.byteLength})`), "__NEXT_ERROR_CODE", {
value: "E808",
enumerable: false,
configurable: true
});
}
}
if ((typeof exports.default === 'function' || (typeof exports.default === 'object' && exports.default !== null)) && typeof exports.default.__esModule === 'undefined') {
Object.defineProperty(exports.default, '__esModule', { value: true });
Object.assign(exports.default, exports);
module.exports = exports.default;
}
//# sourceMappingURL=web-socket.js.map