perf: self-host fonts, drop unused generated code and add swf tests
CI / check (push) Successful in 25s
CI / release (push) Skipped
CI / deploy (push) Successful in 59s

- 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:
openhands committed 2026-08-09 12:12:02 +02:00
1 parent ae1393d3e3
commit 4993b75608
7 files changed
+330 -23

No files matched your search

+1 -1
View File
@@ -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: {
-6
View File
@@ -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
View File
@@ -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"
+85
View File
@@ -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);
});
});
+62
View File
@@ -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
View File
@@ -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"]
}