88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
import { Agentation } from 'agentation'
|
|
import { GeistPixelSquare } from 'geist/font/pixel'
|
|
import { Barlow } from 'next/font/google'
|
|
import localFont from 'next/font/local'
|
|
import Script from 'next/script'
|
|
import { ClientBootstrap } from './client-bootstrap'
|
|
import './globals.css'
|
|
|
|
const chunkRecoveryScript = `
|
|
(() => {
|
|
const marker = 'pascal:chunk-recovery-at'
|
|
const recoveryParam = '__pascal_reload'
|
|
const chunkError = /ChunkLoadError|Failed to load chunk|Loading chunk .* failed|CSS_CHUNK_LOAD_FAILED/i
|
|
|
|
const recover = (event) => {
|
|
const reason = event?.reason
|
|
const message = [
|
|
event?.message,
|
|
reason?.message,
|
|
typeof reason === 'string' ? reason : '',
|
|
].filter(Boolean).join(' ')
|
|
if (!chunkError.test(message)) return
|
|
|
|
const now = Date.now()
|
|
const lastRecovery = Number(sessionStorage.getItem(marker) || 0)
|
|
if (now - lastRecovery < 60000) return
|
|
|
|
sessionStorage.setItem(marker, String(now))
|
|
const url = new URL(window.location.href)
|
|
url.searchParams.set(recoveryParam, String(now))
|
|
window.location.replace(url.toString())
|
|
}
|
|
|
|
window.addEventListener('error', recover, true)
|
|
window.addEventListener('unhandledrejection', recover)
|
|
|
|
window.setTimeout(() => {
|
|
sessionStorage.removeItem(marker)
|
|
const url = new URL(window.location.href)
|
|
if (!url.searchParams.has(recoveryParam)) return
|
|
url.searchParams.delete(recoveryParam)
|
|
window.history.replaceState(window.history.state, '', url.toString())
|
|
}, 10000)
|
|
})()
|
|
`
|
|
|
|
const geistSans = localFont({
|
|
src: './fonts/GeistVF.woff',
|
|
variable: '--font-geist-sans',
|
|
})
|
|
const geistMono = localFont({
|
|
src: './fonts/GeistMonoVF.woff',
|
|
variable: '--font-geist-mono',
|
|
})
|
|
|
|
const barlow = Barlow({
|
|
subsets: ['latin'],
|
|
weight: ['400', '500', '600', '700'],
|
|
variable: '--font-barlow',
|
|
display: 'swap',
|
|
})
|
|
|
|
export default function RootLayout({
|
|
children,
|
|
}: Readonly<{
|
|
children: React.ReactNode
|
|
}>) {
|
|
return (
|
|
<html
|
|
className={`${geistSans.variable} ${geistMono.variable} ${GeistPixelSquare.variable} ${barlow.variable}`}
|
|
lang="zh-CN"
|
|
>
|
|
<head>
|
|
<Script id="pascal-chunk-recovery" strategy="beforeInteractive">
|
|
{chunkRecoveryScript}
|
|
</Script>
|
|
{process.env.NODE_ENV === 'development' && (
|
|
<script async crossOrigin="anonymous" src="//unpkg.com/react-scan/dist/auto.global.js" />
|
|
)}
|
|
</head>
|
|
<body className="font-sans">
|
|
<ClientBootstrap>{children}</ClientBootstrap>
|
|
{process.env.NODE_ENV === 'development' && <Agentation />}
|
|
</body>
|
|
</html>
|
|
)
|
|
}
|