🐛 FIX: Next.js Build Errors on Table Click + Next.js Deployment issue
This commit is contained in:
parent
065dc6aa9a
commit
9e80d899d6
@ -988,8 +988,11 @@ export const ChatPanel = forwardRef<ChatPanelHandle, ChatPanelProps>(
|
||||
status === "submitted" ||
|
||||
isReconnecting;
|
||||
|
||||
const onRuntimeStateChangeRef = useRef(onRuntimeStateChange);
|
||||
onRuntimeStateChangeRef.current = onRuntimeStateChange;
|
||||
|
||||
useEffect(() => {
|
||||
onRuntimeStateChange?.({
|
||||
onRuntimeStateChangeRef.current?.({
|
||||
sessionId: currentSessionId,
|
||||
sessionKey: subagentSessionKey ?? null,
|
||||
isStreaming,
|
||||
@ -1004,7 +1007,6 @@ export const ChatPanel = forwardRef<ChatPanelHandle, ChatPanelProps>(
|
||||
status,
|
||||
isReconnecting,
|
||||
loadingSession,
|
||||
onRuntimeStateChange,
|
||||
]);
|
||||
|
||||
// Stream stall detection: if we stay in "submitted" (no first
|
||||
|
||||
73
apps/web/app/global-error.tsx
Normal file
73
apps/web/app/global-error.tsx
Normal file
@ -0,0 +1,73 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect } from "react";
|
||||
|
||||
function isChunkLoadError(error: Error & { name?: string }): boolean {
|
||||
if (error.name === "ChunkLoadError") return true;
|
||||
if (error.message?.includes("Loading chunk")) return true;
|
||||
if (error.message?.includes("Loading CSS chunk")) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
export default function GlobalError({
|
||||
error,
|
||||
reset,
|
||||
}: {
|
||||
error: Error & { digest?: string };
|
||||
reset: () => void;
|
||||
}) {
|
||||
useEffect(() => {
|
||||
if (isChunkLoadError(error)) {
|
||||
const key = "__chunk_reload";
|
||||
if (!sessionStorage.getItem(key)) {
|
||||
sessionStorage.setItem(key, "1");
|
||||
window.location.reload();
|
||||
return;
|
||||
}
|
||||
sessionStorage.removeItem(key);
|
||||
}
|
||||
}, [error]);
|
||||
|
||||
return (
|
||||
<html lang="en">
|
||||
<body
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
height: "100vh",
|
||||
fontFamily: "Inter, system-ui, sans-serif",
|
||||
background: "#0a0a0a",
|
||||
color: "#e5e5e5",
|
||||
}}
|
||||
>
|
||||
<div style={{ textAlign: "center", maxWidth: 420, padding: 24 }}>
|
||||
<h2 style={{ fontSize: 20, fontWeight: 600, marginBottom: 8 }}>
|
||||
{isChunkLoadError(error)
|
||||
? "A new version is available"
|
||||
: "Something went wrong"}
|
||||
</h2>
|
||||
<p style={{ fontSize: 14, color: "#a3a3a3", marginBottom: 20 }}>
|
||||
{isChunkLoadError(error)
|
||||
? "The app was updated while you had it open. Reload to get the latest version."
|
||||
: "An unexpected error occurred. Try reloading the page."}
|
||||
</p>
|
||||
<button
|
||||
onClick={() => window.location.reload()}
|
||||
style={{
|
||||
padding: "8px 20px",
|
||||
borderRadius: 6,
|
||||
border: "1px solid #333",
|
||||
background: "#1a1a1a",
|
||||
color: "#e5e5e5",
|
||||
cursor: "pointer",
|
||||
fontSize: 14,
|
||||
}}
|
||||
>
|
||||
Reload
|
||||
</button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@ -31,6 +31,25 @@ export default function RootLayout({
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<head>
|
||||
<script
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `(function(){
|
||||
var k='__chunk_reload';
|
||||
if(sessionStorage.getItem(k)){sessionStorage.removeItem(k);return}
|
||||
function reload(){sessionStorage.setItem(k,'1');window.location.reload()}
|
||||
window.addEventListener('error',function(e){
|
||||
var t=e.target;
|
||||
if(t&&(t.tagName==='SCRIPT'||t.tagName==='LINK')){
|
||||
var s=t.src||t.href||'';
|
||||
if(s.indexOf('_next/static')!==-1)reload();
|
||||
}
|
||||
},true);
|
||||
window.addEventListener('unhandledrejection',function(e){
|
||||
if(e.reason&&e.reason.name==='ChunkLoadError')reload();
|
||||
});
|
||||
})();`,
|
||||
}}
|
||||
/>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link
|
||||
rel="preconnect"
|
||||
|
||||
@ -724,6 +724,31 @@ function ensureStaticAssets(runtimeAppDir: string, packageRoot: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* After installing a new build, merge the previous build's `.next/static`
|
||||
* into the new one (without overwriting). This keeps old chunk / CSS files
|
||||
* available so that browser tabs still running the previous version can
|
||||
* finish loading lazily-imported routes instead of hitting 400s.
|
||||
*/
|
||||
function preservePreviousStaticAssets(
|
||||
backupDir: string,
|
||||
runtimeAppDir: string,
|
||||
): void {
|
||||
const oldStatic = path.join(backupDir, ".next", "static");
|
||||
const newStatic = path.join(runtimeAppDir, ".next", "static");
|
||||
if (!existsSync(oldStatic) || !existsSync(newStatic)) return;
|
||||
try {
|
||||
cpSync(oldStatic, newStatic, {
|
||||
recursive: true,
|
||||
force: false,
|
||||
errorOnExist: false,
|
||||
dereference: true,
|
||||
});
|
||||
} catch {
|
||||
// best-effort — stale clients will reload via the chunk-error handler
|
||||
}
|
||||
}
|
||||
|
||||
export function installManagedWebRuntime(params: {
|
||||
stateDir: string;
|
||||
packageRoot: string;
|
||||
@ -765,6 +790,7 @@ export function installManagedWebRuntime(params: {
|
||||
|
||||
dereferenceRuntimeNodeModules(runtimeAppDir, standaloneDir);
|
||||
ensureStaticAssets(runtimeAppDir, params.packageRoot);
|
||||
preservePreviousStaticAssets(backupDir, runtimeAppDir);
|
||||
ensureSeedAssets(runtimeAppDir, params.packageRoot);
|
||||
|
||||
const manifest: ManagedWebRuntimeManifest = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user