@redwoodjs/sdk
Version:
A full-stack webapp toolkit designed for TypeScript, Vite, and React Server Components
52 lines (51 loc) • 2.4 kB
JavaScript
export const injectHMRPreamble = () => {
let headFound = false;
const hmrScript = `
<script>
import RefreshRuntime from "/@react-refresh"
RefreshRuntime.injectIntoGlobalHook(window)
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
</script>
`;
return new TransformStream({
transform(chunk, controller) {
if (!headFound) {
const chunkStr = new TextDecoder().decode(chunk);
const headMatch = chunkStr.match(/<head[^>]*>/i);
if (headMatch) {
headFound = true;
const index = headMatch.index + headMatch[0].length;
const before = chunkStr.slice(0, index);
const after = chunkStr.slice(index);
const firstScriptMatch = after.match(/<script[^>]*>/i);
if (firstScriptMatch) {
// Insert before the first script
const scriptIndex = firstScriptMatch.index;
const beforeScript = after.slice(0, scriptIndex);
const afterScript = after.slice(scriptIndex);
controller.enqueue(new TextEncoder().encode(before + beforeScript + hmrScript + afterScript));
}
else {
// If no script tags found, check for </head>
const headEndMatch = after.match(/<\/head>/i);
if (headEndMatch) {
// Insert before </head>
const headEndIndex = headEndMatch.index;
const beforeHeadEnd = after.slice(0, headEndIndex);
const afterHeadEnd = after.slice(headEndIndex);
controller.enqueue(new TextEncoder().encode(before + beforeHeadEnd + hmrScript + afterHeadEnd));
}
else {
// If we haven't found </head> yet, just append after <head>
controller.enqueue(new TextEncoder().encode(before + hmrScript + after));
}
}
return;
}
}
controller.enqueue(chunk);
}
});
};