forked from vercel/turborepo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
793262f
commit ff7c02a
Showing
84 changed files
with
5,059 additions
and
4,964 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "@vercel/turbopack-next", | ||
"version": "0.0.0", | ||
"description": "turbopack next runtime", | ||
"license": "UNLICENSED", | ||
"private": true, | ||
"scripts": { | ||
"check": "tsc --noEmit" | ||
}, | ||
"dependencies": { | ||
"@next/react-refresh-utils": "^12.2.5", | ||
"@vercel/turbopack-runtime": "latest", | ||
"next": "^12.3.1", | ||
"react": "^18.2.0", | ||
"react-dom": "^18.2.0" | ||
}, | ||
"devDependencies": { | ||
"@types/node": "^18.8.4", | ||
"@types/react": "^18.0.21", | ||
"@types/react-dom": "^18.0.6" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { connect } from "./hmr-client"; | ||
import { connectHMR } from "./websocket"; | ||
|
||
export function initializeHMR(options: { assetPrefix: string }) { | ||
connect(); | ||
connectHMR({ | ||
path: "/turbopack-hmr", | ||
assetPrefix: options.assetPrefix, | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import type { | ||
ClientMessage, | ||
ServerMessage, | ||
} from "@vercel/turbopack-runtime/types/protocol"; | ||
import type { | ||
ChunkId, | ||
ChunkUpdateCallback, | ||
TurbopackGlobals, | ||
} from "@vercel/turbopack-runtime/types"; | ||
|
||
import { addEventListener, sendMessage } from "./websocket"; | ||
|
||
declare var globalThis: TurbopackGlobals; | ||
|
||
export function connect() { | ||
addEventListener((event) => { | ||
switch (event.type) { | ||
case "connected": | ||
handleSocketConnected(); | ||
break; | ||
case "message": | ||
handleSocketMessage(event.message); | ||
break; | ||
} | ||
}); | ||
|
||
const queued = globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS; | ||
if (queued != null && !Array.isArray(queued)) { | ||
throw new Error("A separate HMR handler was already registered"); | ||
} | ||
globalThis.TURBOPACK_CHUNK_UPDATE_LISTENERS = { | ||
push: ([chunkId, callback]: [ChunkId, ChunkUpdateCallback]) => { | ||
onChunkUpdate(chunkId, callback); | ||
}, | ||
}; | ||
|
||
if (Array.isArray(queued)) { | ||
for (const [chunkId, callback] of queued) { | ||
onChunkUpdate(chunkId, callback); | ||
} | ||
} | ||
|
||
subscribeToInitialCssChunksUpdates(); | ||
} | ||
|
||
const chunkUpdateCallbacks: Map<ChunkId, ChunkUpdateCallback[]> = new Map(); | ||
|
||
function sendJSON(message: ClientMessage) { | ||
sendMessage(JSON.stringify(message)); | ||
} | ||
|
||
function subscribeToChunkUpdates(chunkId: ChunkId) { | ||
sendJSON({ | ||
type: "subscribe", | ||
chunkId, | ||
}); | ||
} | ||
|
||
function handleSocketConnected() { | ||
for (const chunkId of chunkUpdateCallbacks.keys()) { | ||
subscribeToChunkUpdates(chunkId); | ||
} | ||
} | ||
|
||
function handleSocketMessage(event: MessageEvent) { | ||
const data: ServerMessage = JSON.parse(event.data); | ||
|
||
triggerChunkUpdate(data); | ||
} | ||
|
||
export function onChunkUpdate(chunkId: ChunkId, callback: ChunkUpdateCallback) { | ||
const callbacks = chunkUpdateCallbacks.get(chunkId); | ||
if (!callbacks) { | ||
chunkUpdateCallbacks.set(chunkId, [callback]); | ||
} else { | ||
callbacks.push(callback); | ||
} | ||
|
||
subscribeToChunkUpdates(chunkId); | ||
} | ||
|
||
function triggerChunkUpdate(update: ServerMessage) { | ||
const callbacks = chunkUpdateCallbacks.get(update.chunkId); | ||
if (!callbacks) { | ||
return; | ||
} | ||
|
||
try { | ||
for (const callback of callbacks) { | ||
callback(update); | ||
} | ||
} catch (err) { | ||
console.error( | ||
`An error occurred during the update of chunk \`${update.chunkId}\``, | ||
err | ||
); | ||
location.reload(); | ||
} | ||
} | ||
|
||
// Unlike ES chunks, CSS chunks cannot contain the logic to accept updates. | ||
// They must be reloaded here instead. | ||
function subscribeToInitialCssChunksUpdates() { | ||
const initialCssChunkLinks: NodeListOf<HTMLLinkElement> = | ||
document.head.querySelectorAll("link[data-turbopack-chunk-id]"); | ||
initialCssChunkLinks.forEach((link) => { | ||
const chunkId = link.dataset.turbopackChunkId!; | ||
|
||
onChunkUpdate(chunkId, (update) => { | ||
switch (update.type) { | ||
case "restart": { | ||
console.info(`Reloading CSS chunk \`${chunkId}\``); | ||
link.replaceWith(link); | ||
break; | ||
} | ||
case "partial": | ||
throw new Error(`partial CSS chunk updates are not supported`); | ||
default: | ||
throw new Error(`unknown update type \`${update}\``); | ||
} | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
// Adapted from https://github.com/vercel/next.js/blob/canary/packages/next/client/dev/error-overlay/websocket.ts | ||
|
||
let source: WebSocket; | ||
const eventCallbacks: ((event: WebsocketEvent) => void)[] = []; | ||
|
||
// TODO: add timeout again | ||
// let lastActivity = Date.now() | ||
|
||
function getSocketProtocol(assetPrefix: string): string { | ||
let protocol = location.protocol; | ||
|
||
try { | ||
// assetPrefix is a url | ||
protocol = new URL(assetPrefix).protocol; | ||
} catch (_) {} | ||
|
||
return protocol === "http:" ? "ws" : "wss"; | ||
} | ||
|
||
type WebsocketEvent = | ||
| { | ||
type: "connected"; | ||
} | ||
| { | ||
type: "message"; | ||
message: MessageEvent; | ||
}; | ||
|
||
export function addEventListener(cb: (event: WebsocketEvent) => void) { | ||
eventCallbacks.push(cb); | ||
} | ||
|
||
export function sendMessage(data: any) { | ||
if (!source || source.readyState !== source.OPEN) return; | ||
return source.send(data); | ||
} | ||
|
||
export type HMROptions = { | ||
path: string; | ||
assetPrefix: string; | ||
timeout?: number; | ||
log?: boolean; | ||
}; | ||
|
||
export function connectHMR(options: HMROptions) { | ||
const { timeout = 5 * 1000 } = options; | ||
|
||
function init() { | ||
if (source) source.close(); | ||
|
||
function handleOnline() { | ||
eventCallbacks.forEach((cb) => { | ||
cb({ | ||
type: "connected", | ||
}); | ||
}); | ||
|
||
if (options.log) console.log("[HMR] connected"); | ||
// lastActivity = Date.now() | ||
} | ||
|
||
function handleMessage(event: MessageEvent) { | ||
// lastActivity = Date.now() | ||
|
||
eventCallbacks.forEach((cb) => { | ||
cb({ | ||
type: "message", | ||
message: event, | ||
}); | ||
}); | ||
} | ||
|
||
// let timer: NodeJS.Timeout | ||
|
||
function handleDisconnect() { | ||
// clearInterval(timer) | ||
source.close(); | ||
setTimeout(init, timeout); | ||
} | ||
|
||
// timer = setInterval(function() { | ||
// if (Date.now() - lastActivity > timeout) { | ||
// handleDisconnect() | ||
// } | ||
// }, timeout / 2) | ||
|
||
const { hostname, port } = location; | ||
const protocol = getSocketProtocol(options.assetPrefix || ""); | ||
const assetPrefix = options.assetPrefix.replace(/^\/+/, ""); | ||
|
||
let url = `${protocol}://${hostname}:${port}${ | ||
assetPrefix ? `/${assetPrefix}` : "" | ||
}`; | ||
|
||
if (assetPrefix.startsWith("http")) { | ||
url = `${protocol}://${assetPrefix.split("://")[1]}`; | ||
} | ||
|
||
source = new window.WebSocket(`${url}${options.path}`); | ||
source.onopen = handleOnline; | ||
source.onerror = handleDisconnect; | ||
source.onmessage = handleMessage; | ||
} | ||
|
||
init(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// this file is just here to make typescript happy about the wrapped/virtual assets (import ".") | ||
|
||
declare var Anything: any; | ||
export = Anything; |
11 changes: 9 additions & 2 deletions
11
crates/next-core/js/entry/next-hydrate.js → ...s/next-core/js/src/entry/next-hydrate.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.