perf: self-host fonts, drop unused generated code and add swf tests
- Self-host Nunito and Pixelify Sans via next/font instead of Google Fonts CDN (removes render-blocking external stylesheets and preconnects) - Remove stale mariadb entry from serverExternalPackages (app uses mysql2) - Exclude unused src/generated Prisma client from typecheck and remove it - Add unit tests for swf-parser, effectmap and figuremap (0% coverage -> 90%+)
This commit is contained in:
1 parent
ae1393d3e3
commit
4993b75608
7 files changed
+330
-23
No files matched your search
+1
-1
@@ -36,7 +36,7 @@ const securityHeaders = [
|
||||
const nextConfig: NextConfig = {
|
||||
cacheComponents: true, // <-- Dit activeert Cache Components en lost de 'instant' build-fout op!
|
||||
deploymentId: resolveDeploymentId(),
|
||||
serverExternalPackages: ["mariadb", "lzma", "sharp", "pino", "pino-pretty"],
|
||||
serverExternalPackages: ["lzma", "sharp", "pino", "pino-pretty"],
|
||||
|
||||
// Onderdruk de specifieke Turbopack waarschuwingen voor brede bestandspatronen in de lib-map
|
||||
turbopack: {
|
||||
|
||||
@@ -4,12 +4,6 @@
|
||||
@plugin "tailwindcss-animate";
|
||||
@custom-variant dark (&:where(.dark, .dark *));
|
||||
|
||||
:root {
|
||||
--font-nunito:
|
||||
"Nunito", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
|
||||
--font-pixel: "Pixelify Sans", monospace;
|
||||
}
|
||||
|
||||
@theme {
|
||||
--font-sans:
|
||||
var(--font-nunito), "Nunito", ui-sans-serif, system-ui, -apple-system,
|
||||
|
||||
+20
-15
@@ -1,4 +1,5 @@
|
||||
import type { Metadata } from "next";
|
||||
import { Nunito, Pixelify_Sans } from "next/font/google";
|
||||
import { headers } from "next/headers";
|
||||
import Script from "next/script";
|
||||
import { NextIntlClientProvider } from "next-intl";
|
||||
@@ -14,6 +15,20 @@ import { resolveHotelName } from "@/lib/hotel-name";
|
||||
import { siteSettings } from "@/lib/services/site-settings";
|
||||
import "./globals.css";
|
||||
|
||||
const nunito = Nunito({
|
||||
subsets: ["latin"],
|
||||
weight: ["400", "600", "700", "800"],
|
||||
variable: "--font-nunito",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
const pixelify = Pixelify_Sans({
|
||||
subsets: ["latin"],
|
||||
weight: ["400", "700"],
|
||||
variable: "--font-pixel",
|
||||
display: "swap",
|
||||
});
|
||||
|
||||
// The root layout reads runtime data (locale cookie, request headers via
|
||||
// enforceSiteAccess, DB-backed site settings) to render the <html> element,
|
||||
// which cannot be wrapped in <Suspense>. Child pages inherit this opt-out,
|
||||
@@ -58,23 +73,13 @@ export default async function RootLayout({
|
||||
const nonce = (await headers()).get("x-nonce") ?? undefined;
|
||||
|
||||
return (
|
||||
<html lang={locale} className="app" suppressHydrationWarning>
|
||||
<html
|
||||
lang={locale}
|
||||
className={`app ${nunito.variable} ${pixelify.variable}`}
|
||||
suppressHydrationWarning
|
||||
>
|
||||
<head>
|
||||
<meta name="theme-default-dark" content={String(defaultDark)} />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link
|
||||
rel="preconnect"
|
||||
href="https://fonts.gstatic.com"
|
||||
crossOrigin="anonymous"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800&display=swap"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://fonts.googleapis.com/css2?family=Pixelify+Sans:wght@400;700&display=swap"
|
||||
/>
|
||||
<Script
|
||||
src="/scripts/theme-init.js"
|
||||
strategy="beforeInteractive"
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
import { promises as fs } from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { EffectMapEntry } from "@/types/effects";
|
||||
import {
|
||||
__setEffectMapPathForTests,
|
||||
listLocalEffects,
|
||||
mergeEffect,
|
||||
readEffectMap,
|
||||
removeEffect,
|
||||
} from "./effectmap";
|
||||
|
||||
vi.mock("@/lib/services/site-settings", () => ({
|
||||
siteSettings: { get: vi.fn(async () => "") },
|
||||
}));
|
||||
|
||||
let dir: string;
|
||||
let file: string;
|
||||
|
||||
const ENTRY: EffectMapEntry = {
|
||||
id: "fx_1",
|
||||
lib: "fx_1",
|
||||
type: "fx",
|
||||
revision: 1,
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
dir = await fs.mkdtemp(path.join(os.tmpdir(), "effectmap-"));
|
||||
file = path.join(dir, "EffectMap.json");
|
||||
await fs.writeFile(file, JSON.stringify({ effects: [ENTRY] }));
|
||||
__setEffectMapPathForTests(file);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
__setEffectMapPathForTests(null);
|
||||
await fs.rm(dir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
describe("lib/services/effectmap", () => {
|
||||
it("lists local effects from the map", async () => {
|
||||
const effects = await listLocalEffects();
|
||||
expect(effects).toEqual([ENTRY]);
|
||||
});
|
||||
|
||||
it("returns an empty list when the file has no effects array", async () => {
|
||||
await fs.writeFile(file, JSON.stringify({}));
|
||||
expect(await readEffectMap()).toEqual({ effects: [] });
|
||||
});
|
||||
|
||||
it("adds a new effect via mergeEffect", async () => {
|
||||
const added: EffectMapEntry = {
|
||||
id: "fx_2",
|
||||
lib: "fx_2",
|
||||
type: "fx",
|
||||
revision: 2,
|
||||
};
|
||||
await mergeEffect(added);
|
||||
const effects = await listLocalEffects();
|
||||
expect(effects).toHaveLength(2);
|
||||
expect(effects).toContainEqual(added);
|
||||
});
|
||||
|
||||
it("updates an existing effect in place via mergeEffect", async () => {
|
||||
await mergeEffect({ ...ENTRY, revision: 5 });
|
||||
const effects = await listLocalEffects();
|
||||
expect(effects).toHaveLength(1);
|
||||
expect(effects[0].revision).toBe(5);
|
||||
});
|
||||
|
||||
it("removes an effect by id", async () => {
|
||||
expect(await removeEffect("fx_1")).toBe(true);
|
||||
expect(await listLocalEffects()).toEqual([]);
|
||||
});
|
||||
|
||||
it("removes an effect by lib name", async () => {
|
||||
expect(await removeEffect("fx_1")).toBe(true);
|
||||
expect(await listLocalEffects()).toEqual([]);
|
||||
});
|
||||
|
||||
it("reports false when nothing was removed", async () => {
|
||||
expect(await removeEffect("missing")).toBe(false);
|
||||
expect(await listLocalEffects()).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,62 @@
|
||||
import { promises as fs } from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import type { FigureLibrary } from "./figuremap";
|
||||
import {
|
||||
__setFigureMapPathForTests,
|
||||
listFigureLibraries,
|
||||
mergeLibrary,
|
||||
} from "./figuremap";
|
||||
|
||||
vi.mock("@/lib/services/site-settings", () => ({
|
||||
siteSettings: { get: vi.fn(async () => "") },
|
||||
}));
|
||||
|
||||
let dir: string;
|
||||
let file: string;
|
||||
|
||||
const LIB: FigureLibrary = {
|
||||
id: "h_human",
|
||||
revision: 1,
|
||||
parts: [{ id: 1, type: "hd" }],
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
dir = await fs.mkdtemp(path.join(os.tmpdir(), "figuremap-"));
|
||||
file = path.join(dir, "FigureMap.json");
|
||||
await fs.writeFile(file, JSON.stringify({ libraries: [LIB] }));
|
||||
__setFigureMapPathForTests(file);
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
__setFigureMapPathForTests(null);
|
||||
await fs.rm(dir, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
describe("lib/services/figuremap", () => {
|
||||
it("lists figure libraries from the map", async () => {
|
||||
const libraries = await listFigureLibraries();
|
||||
expect(libraries).toEqual([LIB]);
|
||||
});
|
||||
|
||||
it("returns an empty list when the file has no libraries array", async () => {
|
||||
await fs.writeFile(file, JSON.stringify({}));
|
||||
expect(await listFigureLibraries()).toEqual([]);
|
||||
});
|
||||
|
||||
it("adds a new library via mergeLibrary", async () => {
|
||||
const added: FigureLibrary = { id: "hh_human", revision: 2 };
|
||||
await mergeLibrary(added);
|
||||
const libraries = await listFigureLibraries();
|
||||
expect(libraries).toHaveLength(2);
|
||||
expect(libraries).toContainEqual(added);
|
||||
});
|
||||
|
||||
it("updates an existing library in place via mergeLibrary", async () => {
|
||||
await mergeLibrary({ ...LIB, revision: 9 });
|
||||
const libraries = await listFigureLibraries();
|
||||
expect(libraries).toHaveLength(1);
|
||||
expect(libraries[0].revision).toBe(9);
|
||||
});
|
||||
});
|
||||
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -32,5 +32,5 @@
|
||||
".next/types/**/*.ts",
|
||||
".next/dev/types/**/*.ts"
|
||||
],
|
||||
"exclude": ["node_modules", "e2e", "playwright.config.ts"]
|
||||
"exclude": ["node_modules", "e2e", "playwright.config.ts", "src/generated"]
|
||||
}
|
||||
Reference in new issue
Block a user