fix(production) : prevent hydration and service failures
This commit is contained in:
@@ -36,6 +36,7 @@ export default function RootLayout({ children }: LayoutProps<"/">) {
|
||||
<html
|
||||
lang="th"
|
||||
className={`dark ${anuphan.variable} ${geistMono.variable} h-full antialiased`}
|
||||
suppressHydrationWarning
|
||||
>
|
||||
<body className="flex min-h-full flex-col">
|
||||
<PageProgress />
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import Script from "next/script";
|
||||
|
||||
const clientId = process.env.NEXT_PUBLIC_GOOGLE_ADSENSE_CLIENT_ID?.trim();
|
||||
|
||||
export function GoogleAdsense() {
|
||||
@@ -8,10 +6,9 @@ export function GoogleAdsense() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Script
|
||||
id="google-adsense"
|
||||
<script
|
||||
async
|
||||
src={`https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${encodeURIComponent(clientId)}`}
|
||||
strategy="lazyOnload"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -770,7 +770,12 @@ async function executeCatalogSyncJob(initial: CatalogSyncJob, actor: AuditActor)
|
||||
}
|
||||
|
||||
export async function getCurrentCatalogVersion(): Promise<string | null> {
|
||||
try {
|
||||
return (await getCurrentCatalogState())?.version ?? null;
|
||||
} catch (error) {
|
||||
console.error("Unable to read the current catalog version", error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
async function getCurrentCatalogState() {
|
||||
|
||||
@@ -121,10 +121,15 @@ export async function getActiveCatalog() {
|
||||
if (!characters.length) return null;
|
||||
const groupedAliases = aliasesByItem(aliases);
|
||||
const materialByKey = new Map(materials.map((item) => [item.key, item]));
|
||||
let version = "unknown";
|
||||
try {
|
||||
const storage = await getMediaStorage();
|
||||
const { version } = catalogVersionSchema.parse(
|
||||
version = catalogVersionSchema.parse(
|
||||
await storage.file("catalog/current.json").json(),
|
||||
);
|
||||
).version;
|
||||
} catch (error) {
|
||||
console.error("Unable to read the active catalog version", error);
|
||||
}
|
||||
return {
|
||||
version,
|
||||
characters: characters.map((item) => ({ ...catalogCharacterWithUrls(item, materialByKey), aliases: groupedAliases.character.get(item.key) ?? [] })),
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
export function securityHeaders(production: boolean) {
|
||||
const ads = "https://*.googlesyndication.com https://*.doubleclick.net https://*.googleadservices.com https://*.googletagservices.com https://www.google.com";
|
||||
const cloudflareAnalytics = "https://static.cloudflareinsights.com";
|
||||
const adConnections = "https://*.adtrafficquality.google";
|
||||
const policy = [
|
||||
"default-src 'self'",
|
||||
`script-src 'self' 'unsafe-inline' ${production ? "" : "'unsafe-eval'"} https://challenges.cloudflare.com ${ads}`,
|
||||
`script-src 'self' 'unsafe-inline' ${production ? "" : "'unsafe-eval'"} https://challenges.cloudflare.com ${cloudflareAnalytics} ${ads}`,
|
||||
"style-src 'self' 'unsafe-inline'",
|
||||
`img-src 'self' data: blob: https://buzz-cdn.astrxl.dev ${ads}`,
|
||||
"font-src 'self' data:",
|
||||
`connect-src 'self' https://buzz-cdn.astrxl.dev https://challenges.cloudflare.com ${ads}${production ? "" : " ws: wss:"}`,
|
||||
`connect-src 'self' https://buzz-cdn.astrxl.dev https://challenges.cloudflare.com ${adConnections} ${ads}${production ? "" : " ws: wss:"}`,
|
||||
`frame-src https://challenges.cloudflare.com https://www.youtube-nocookie.com ${ads}`,
|
||||
"media-src 'self' blob:",
|
||||
"worker-src 'self' blob:",
|
||||
|
||||
@@ -72,6 +72,8 @@ describe("public rendering performance", () => {
|
||||
expect(adsense).not.toContain('from "@/lib/auth/client"');
|
||||
expect(adsense).toContain('process.env.NODE_ENV !== "production"');
|
||||
expect(adsense).toContain("pagead2.googlesyndication.com");
|
||||
expect(adsense).toContain("<script");
|
||||
expect(adsense).not.toContain('from "next/script"');
|
||||
expect(home).toContain("<GoogleAdsense />");
|
||||
expect(guide).toContain("<GoogleAdsense />");
|
||||
expect(guideSection).toContain("<GoogleAdsense />");
|
||||
@@ -79,4 +81,17 @@ describe("public rendering performance", () => {
|
||||
"google.com, pub-9687404323559597, DIRECT, f08c47fec0942fa0",
|
||||
);
|
||||
});
|
||||
|
||||
it("allows the production analytics and advertising endpoints", async () => {
|
||||
const headers = await repositoryFile("lib/security/headers.ts");
|
||||
|
||||
expect(headers).toContain("https://static.cloudflareinsights.com");
|
||||
expect(headers).toContain("https://*.adtrafficquality.google");
|
||||
});
|
||||
|
||||
it("accepts Next.js deployment metadata on the document root", async () => {
|
||||
const layout = await repositoryFile("app/layout.tsx");
|
||||
|
||||
expect(layout).toContain("suppressHydrationWarning");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user