perf: optimize bundle size and add build optimizations
All checks were successful
CI / update (push) Successful in 1m23s

- Move HTML stripping to server-side to remove cheerio from client bundle (247KB reduction)
- Add terser minification with console/debugger removal
- Enable manual code chunking for chart.js and auth libraries
- Convert TTF fonts to WOFF2 format (~900KB savings)
- Enable brotli/gzip precompression in adapter
- Update CSS to prefer WOFF2 with TTF fallback
This commit is contained in:
2026-01-19 21:46:03 +01:00
parent a48ae3ff3c
commit 5598b19ec9
15 changed files with 217 additions and 48 deletions

View File

@@ -34,6 +34,7 @@
"jsdom": "^27.2.0",
"svelte": "^5.38.6",
"svelte-check": "^4.0.0",
"terser": "^5.46.0",
"tslib": "^2.6.0",
"typescript": "^5.1.6",
"vite": "^7.1.3",

202
pnpm-lock.yaml generated
View File

@@ -10,16 +10,19 @@ importers:
dependencies:
'@auth/sveltekit':
specifier: ^1.11.1
version: 1.11.1(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)
version: 1.11.1(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)
'@sveltejs/adapter-node':
specifier: ^5.0.0
version: 5.3.1(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))
version: 5.3.1(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))
chart.js:
specifier: ^4.5.0
version: 4.5.0
cheerio:
specifier: 1.0.0-rc.12
version: 1.0.0-rc.12
file-type:
specifier: ^19.0.0
version: 19.6.0
ioredis:
specifier: ^5.9.0
version: 5.9.0
@@ -34,23 +37,23 @@ importers:
version: 0.33.5
devDependencies:
'@playwright/test':
specifier: ^1.56.1
specifier: 1.56.1
version: 1.56.1
'@sveltejs/adapter-auto':
specifier: ^6.1.0
version: 6.1.0(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))
version: 6.1.0(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))
'@sveltejs/kit':
specifier: ^2.37.0
version: 2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))
version: 2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
'@sveltejs/vite-plugin-svelte':
specifier: ^6.1.3
version: 6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))
version: 6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
'@testing-library/jest-dom':
specifier: ^6.9.1
version: 6.9.1
'@testing-library/svelte':
specifier: ^5.2.9
version: 5.2.9(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))(vitest@4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0))
version: 5.2.9(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))(vitest@4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0)(terser@5.46.0))
'@types/node':
specifier: ^22.12.0
version: 22.18.0
@@ -69,6 +72,9 @@ importers:
svelte-check:
specifier: ^4.0.0
version: 4.3.1(picomatch@4.0.3)(svelte@5.38.6)(typescript@5.1.6)
terser:
specifier: ^5.46.0
version: 5.46.0
tslib:
specifier: ^2.6.0
version: 2.6.0
@@ -77,10 +83,10 @@ importers:
version: 5.1.6
vite:
specifier: ^7.1.3
version: 7.1.3(@types/node@22.18.0)
version: 7.1.3(@types/node@22.18.0)(terser@5.46.0)
vitest:
specifier: ^4.0.10
version: 4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0)
version: 4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0)(terser@5.46.0)
packages:
@@ -141,6 +147,9 @@ packages:
resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==}
engines: {node: '>=6.9.0'}
'@borewit/text-codec@0.2.1':
resolution: {integrity: sha512-k7vvKPbf7J2fZ5klGRD9AeKfUvojuZIQ3BT5u7Jfv+puwXkUBUT5PVyMDfJZpy30CBDXGMgw7fguK/lpOMBvgw==}
'@csstools/color-helpers@5.1.0':
resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==}
engines: {node: '>=18'}
@@ -450,6 +459,9 @@ packages:
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
engines: {node: '>=6.0.0'}
'@jridgewell/source-map@0.3.11':
resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==}
'@jridgewell/sourcemap-codec@1.4.15':
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
@@ -626,6 +638,9 @@ packages:
cpu: [x64]
os: [win32]
'@sec-ant/readable-stream@0.4.1':
resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==}
'@standard-schema/spec@1.0.0':
resolution: {integrity: sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==}
@@ -693,6 +708,9 @@ packages:
vitest:
optional: true
'@tokenizer/token@0.3.0':
resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==}
'@types/aria-query@5.0.4':
resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
@@ -802,6 +820,9 @@ packages:
resolution: {integrity: sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==}
engines: {node: '>=16.20.1'}
buffer-from@1.1.2:
resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
chai@6.2.1:
resolution: {integrity: sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg==}
engines: {node: '>=18'}
@@ -843,6 +864,9 @@ packages:
resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==}
engines: {node: '>=12.5.0'}
commander@2.20.3:
resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
commondir@1.0.1:
resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==}
@@ -984,6 +1008,10 @@ packages:
fflate@0.8.2:
resolution: {integrity: sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==}
file-type@19.6.0:
resolution: {integrity: sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ==}
engines: {node: '>=18'}
flatted@3.3.3:
resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==}
@@ -1000,6 +1028,10 @@ packages:
function-bind@1.1.1:
resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==}
get-stream@9.0.1:
resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==}
engines: {node: '>=18'}
has@1.0.3:
resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==}
engines: {node: '>= 0.4.0'}
@@ -1023,6 +1055,9 @@ packages:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
engines: {node: '>=0.10.0'}
ieee754@1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
indent-string@4.0.0:
resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
engines: {node: '>=8'}
@@ -1052,6 +1087,10 @@ packages:
is-reference@3.0.3:
resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==}
is-stream@4.0.1:
resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==}
engines: {node: '>=18'}
jose@6.1.0:
resolution: {integrity: sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==}
@@ -1194,6 +1233,10 @@ packages:
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
peek-readable@5.4.2:
resolution: {integrity: sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg==}
engines: {node: '>=14.16'}
picocolors@1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
@@ -1325,6 +1368,13 @@ packages:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
source-map-support@0.5.21:
resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
sparse-bitfield@3.0.3:
resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==}
@@ -1341,6 +1391,10 @@ packages:
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
engines: {node: '>=8'}
strtok3@9.1.1:
resolution: {integrity: sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw==}
engines: {node: '>=16'}
supports-preserve-symlinks-flag@1.0.0:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'}
@@ -1360,6 +1414,11 @@ packages:
symbol-tree@3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
terser@5.46.0:
resolution: {integrity: sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==}
engines: {node: '>=10'}
hasBin: true
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
@@ -1385,6 +1444,10 @@ packages:
resolution: {integrity: sha512-lCcgTAgMxQ1JKOWrVGo6E69Ukbnx4Gc1wiYLRf6J5NN4HRYJtCby1rPF8rkQ4a6qqoFBK5dvjJ1zJ0F7VfDSvw==}
hasBin: true
token-types@6.1.2:
resolution: {integrity: sha512-dRXchy+C0IgK8WPC6xvCHFRIWYUbqqdEIKPaKo/AcTUNzwLTK6AH7RjdLWsEZcAN/TBdtfUw3PYEgPr5VPr6ww==}
engines: {node: '>=14.16'}
totalist@3.0.1:
resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==}
engines: {node: '>=6'}
@@ -1409,6 +1472,10 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
uint8array-extras@1.5.0:
resolution: {integrity: sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==}
engines: {node: '>=18'}
undici-types@6.21.0:
resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==}
@@ -1581,10 +1648,10 @@ snapshots:
preact: 10.24.3
preact-render-to-string: 6.5.11(preact@10.24.3)
'@auth/sveltekit@1.11.1(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)':
'@auth/sveltekit@1.11.1(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)':
dependencies:
'@auth/core': 0.41.1
'@sveltejs/kit': 2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))
'@sveltejs/kit': 2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
set-cookie-parser: 2.7.1
svelte: 5.38.6
@@ -1598,6 +1665,8 @@ snapshots:
'@babel/runtime@7.28.4': {}
'@borewit/text-codec@0.2.1': {}
'@csstools/color-helpers@5.1.0': {}
'@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)':
@@ -1792,6 +1861,11 @@ snapshots:
'@jridgewell/resolve-uri@3.1.0': {}
'@jridgewell/source-map@0.3.11':
dependencies:
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.30
'@jridgewell/sourcemap-codec@1.4.15': {}
'@jridgewell/sourcemap-codec@1.5.5': {}
@@ -1922,29 +1996,31 @@ snapshots:
'@rollup/rollup-win32-x64-msvc@4.50.0':
optional: true
'@sec-ant/readable-stream@0.4.1': {}
'@standard-schema/spec@1.0.0': {}
'@sveltejs/acorn-typescript@1.0.5(acorn@8.15.0)':
dependencies:
acorn: 8.15.0
'@sveltejs/adapter-auto@6.1.0(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))':
'@sveltejs/adapter-auto@6.1.0(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))':
dependencies:
'@sveltejs/kit': 2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))
'@sveltejs/kit': 2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
'@sveltejs/adapter-node@5.3.1(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))':
'@sveltejs/adapter-node@5.3.1(@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))':
dependencies:
'@rollup/plugin-commonjs': 28.0.6(rollup@4.50.0)
'@rollup/plugin-json': 6.1.0(rollup@4.50.0)
'@rollup/plugin-node-resolve': 16.0.1(rollup@4.50.0)
'@sveltejs/kit': 2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))
'@sveltejs/kit': 2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
rollup: 4.50.0
'@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))':
'@sveltejs/kit@2.37.0(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))':
dependencies:
'@standard-schema/spec': 1.0.0
'@sveltejs/acorn-typescript': 1.0.5(acorn@8.15.0)
'@sveltejs/vite-plugin-svelte': 6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))
'@sveltejs/vite-plugin-svelte': 6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
'@types/cookie': 0.6.0
acorn: 8.15.0
cookie: 0.6.0
@@ -1957,27 +2033,27 @@ snapshots:
set-cookie-parser: 2.6.0
sirv: 3.0.1
svelte: 5.38.6
vite: 7.1.3(@types/node@22.18.0)
vite: 7.1.3(@types/node@22.18.0)(terser@5.46.0)
'@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))':
'@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))':
dependencies:
'@sveltejs/vite-plugin-svelte': 6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))
'@sveltejs/vite-plugin-svelte': 6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
debug: 4.4.1
svelte: 5.38.6
vite: 7.1.3(@types/node@22.18.0)
vite: 7.1.3(@types/node@22.18.0)(terser@5.46.0)
transitivePeerDependencies:
- supports-color
'@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))':
'@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))':
dependencies:
'@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))
'@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.1.3(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)))(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
debug: 4.4.1
deepmerge: 4.3.1
kleur: 4.1.5
magic-string: 0.30.18
svelte: 5.38.6
vite: 7.1.3(@types/node@22.18.0)
vitefu: 1.1.1(vite@7.1.3(@types/node@22.18.0))
vite: 7.1.3(@types/node@22.18.0)(terser@5.46.0)
vitefu: 1.1.1(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
transitivePeerDependencies:
- supports-color
@@ -2001,13 +2077,15 @@ snapshots:
picocolors: 1.1.1
redent: 3.0.0
'@testing-library/svelte@5.2.9(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0))(vitest@4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0))':
'@testing-library/svelte@5.2.9(svelte@5.38.6)(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))(vitest@4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0)(terser@5.46.0))':
dependencies:
'@testing-library/dom': 10.4.1
svelte: 5.38.6
optionalDependencies:
vite: 7.1.3(@types/node@22.18.0)
vitest: 4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0)
vite: 7.1.3(@types/node@22.18.0)(terser@5.46.0)
vitest: 4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0)(terser@5.46.0)
'@tokenizer/token@0.3.0': {}
'@types/aria-query@5.0.4': {}
@@ -2047,13 +2125,13 @@ snapshots:
chai: 6.2.1
tinyrainbow: 3.0.3
'@vitest/mocker@4.0.10(vite@7.1.3(@types/node@22.18.0))':
'@vitest/mocker@4.0.10(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))':
dependencies:
'@vitest/spy': 4.0.10
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
vite: 7.1.3(@types/node@22.18.0)
vite: 7.1.3(@types/node@22.18.0)(terser@5.46.0)
'@vitest/pretty-format@4.0.10':
dependencies:
@@ -2081,7 +2159,7 @@ snapshots:
sirv: 3.0.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
vitest: 4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0)
vitest: 4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0)(terser@5.46.0)
'@vitest/utils@4.0.10':
dependencies:
@@ -2114,6 +2192,8 @@ snapshots:
bson@6.10.4: {}
buffer-from@1.1.2: {}
chai@6.2.1: {}
chart.js@4.5.0:
@@ -2163,6 +2243,8 @@ snapshots:
color-convert: 2.0.1
color-string: 1.9.1
commander@2.20.3: {}
commondir@1.0.1: {}
cookie@0.6.0: {}
@@ -2296,6 +2378,13 @@ snapshots:
fflate@0.8.2: {}
file-type@19.6.0:
dependencies:
get-stream: 9.0.1
strtok3: 9.1.1
token-types: 6.1.2
uint8array-extras: 1.5.0
flatted@3.3.3: {}
fsevents@2.3.2:
@@ -2306,6 +2395,11 @@ snapshots:
function-bind@1.1.1: {}
get-stream@9.0.1:
dependencies:
'@sec-ant/readable-stream': 0.4.1
is-stream: 4.0.1
has@1.0.3:
dependencies:
function-bind: 1.1.1
@@ -2339,6 +2433,8 @@ snapshots:
dependencies:
safer-buffer: 2.1.2
ieee754@1.2.1: {}
indent-string@4.0.0: {}
ioredis@5.9.0:
@@ -2376,6 +2472,8 @@ snapshots:
dependencies:
'@types/estree': 1.0.8
is-stream@4.0.1: {}
jose@6.1.0: {}
js-tokens@4.0.0: {}
@@ -2510,6 +2608,8 @@ snapshots:
pathe@2.0.3: {}
peek-readable@5.4.2: {}
picocolors@1.0.0: {}
picocolors@1.1.1: {}
@@ -2669,6 +2769,13 @@ snapshots:
source-map-js@1.2.1: {}
source-map-support@0.5.21:
dependencies:
buffer-from: 1.1.2
source-map: 0.6.1
source-map@0.6.1: {}
sparse-bitfield@3.0.3:
dependencies:
memory-pager: 1.5.0
@@ -2683,6 +2790,11 @@ snapshots:
dependencies:
min-indent: 1.0.1
strtok3@9.1.1:
dependencies:
'@tokenizer/token': 0.3.0
peek-readable: 5.4.2
supports-preserve-symlinks-flag@1.0.0: {}
svelte-check@4.3.1(picomatch@4.0.3)(svelte@5.38.6)(typescript@5.1.6):
@@ -2716,6 +2828,13 @@ snapshots:
symbol-tree@3.2.4: {}
terser@5.46.0:
dependencies:
'@jridgewell/source-map': 0.3.11
acorn: 8.15.0
commander: 2.20.3
source-map-support: 0.5.21
tinybench@2.9.0: {}
tinyexec@0.3.2: {}
@@ -2738,6 +2857,12 @@ snapshots:
dependencies:
tldts-core: 7.0.18
token-types@6.1.2:
dependencies:
'@borewit/text-codec': 0.2.1
'@tokenizer/token': 0.3.0
ieee754: 1.2.1
totalist@3.0.1: {}
tough-cookie@6.0.0:
@@ -2756,9 +2881,11 @@ snapshots:
typescript@5.1.6: {}
uint8array-extras@1.5.0: {}
undici-types@6.21.0: {}
vite@7.1.3(@types/node@22.18.0):
vite@7.1.3(@types/node@22.18.0)(terser@5.46.0):
dependencies:
esbuild: 0.25.9
fdir: 6.5.0(picomatch@4.0.3)
@@ -2769,15 +2896,16 @@ snapshots:
optionalDependencies:
'@types/node': 22.18.0
fsevents: 2.3.3
terser: 5.46.0
vitefu@1.1.1(vite@7.1.3(@types/node@22.18.0)):
vitefu@1.1.1(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0)):
optionalDependencies:
vite: 7.1.3(@types/node@22.18.0)
vite: 7.1.3(@types/node@22.18.0)(terser@5.46.0)
vitest@4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0):
vitest@4.0.10(@types/node@22.18.0)(@vitest/ui@4.0.10)(jsdom@27.2.0)(terser@5.46.0):
dependencies:
'@vitest/expect': 4.0.10
'@vitest/mocker': 4.0.10(vite@7.1.3(@types/node@22.18.0))
'@vitest/mocker': 4.0.10(vite@7.1.3(@types/node@22.18.0)(terser@5.46.0))
'@vitest/pretty-format': 4.0.10
'@vitest/runner': 4.0.10
'@vitest/snapshot': 4.0.10
@@ -2794,7 +2922,7 @@ snapshots:
tinyexec: 0.3.2
tinyglobby: 0.2.15
tinyrainbow: 3.0.3
vite: 7.1.3(@types/node@22.18.0)
vite: 7.1.3(@types/node@22.18.0)(terser@5.46.0)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 22.18.0

View File

@@ -3,14 +3,16 @@
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/fonts/crosses.ttf);
src: url(/fonts/crosses.woff2) format('woff2'),
url(/fonts/crosses.ttf) format('truetype');
}
@font-face {
font-family: 'LibertineMinimal';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url(/fonts/LinLibertine_minimal.ttf);
src: url(/fonts/LinLibertine_minimal.woff2) format('woff2'),
url(/fonts/LinLibertine_minimal.ttf) format('truetype');
}
.sbeads{
fill: var(--nord10);

View File

@@ -1,4 +1,19 @@
import { redirect, error } from '@sveltejs/kit';
import { stripHtmlTags } from '$lib/js/stripHtmlTags';
export async function load({ parent }) {
// Get data from universal load function
const data = await parent();
// Strip HTML tags server-side to avoid bundling cheerio in client
const strippedName = stripHtmlTags(data.name);
const strippedDescription = stripHtmlTags(data.description);
return {
strippedName,
strippedDescription,
};
}
export const actions = {
toggleFavorite: async ({ request, locals, url, fetch }) => {

View File

@@ -11,7 +11,6 @@
import { afterNavigate } from '$app/navigation';
import {season} from '$lib/js/season_store';
import RecipeNote from '$lib/components/RecipeNote.svelte';
import {stripHtmlTags} from '$lib/js/stripHtmlTags';
import FavoriteButton from '$lib/components/FavoriteButton.svelte';
import { onDestroy } from 'svelte';
import { recipeTranslationStore } from '$lib/stores/recipeTranslation';
@@ -44,10 +43,8 @@
const hero_img_src = $derived("https://bocken.org/static/rezepte/full/" + img_filename);
const placeholder_src = $derived("https://bocken.org/static/rezepte/placeholder/" + img_filename);
// Get alt text from images array (with fallback to recipe name)
const img_alt = $derived(
data.images?.[0]?.alt || stripHtmlTags(data.name)
);
// Get alt text from images array
const img_alt = $derived(data.images?.[0]?.alt || '');
const months = $derived(isEnglish
? ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
@@ -308,12 +305,12 @@ h2{
</style>
<svelte:head>
<title>{stripHtmlTags(data.name)} - {labels.title}</title>
<meta name="description" content="{stripHtmlTags(data.description)}" />
<title>{data.strippedName} - {labels.title}</title>
<meta name="description" content="{data.strippedDescription}" />
<meta property="og:image" content="https://bocken.org/static/rezepte/thumb/{img_filename}" />
<meta property="og:image:secure_url" content="https://bocken.org/static/rezepte/thumb/{img_filename}" />
<meta property="og:image:type" content="image/webp" />
<meta property="og:image:alt" content="{stripHtmlTags(data.name)}" />
<meta property="og:image:alt" content="{data.strippedName}" />
{@html `<script type="application/ld+json">${JSON.stringify(data.recipeJsonLd)}</script>`}
<!-- SEO: hreflang tags -->
<link rel="alternate" hreflang="de" href="https://bocken.org/rezepte/{data.germanShortName}" />

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -10,7 +10,9 @@ const config = {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter(),
adapter: adapter({
precompress: true // Enable brotli and gzip compression
}),
alias: {
$models: 'src/models',
$utils: 'src/utils'

View File

@@ -6,4 +6,28 @@ export default defineConfig({
allowedHosts: ["bocken.org"]
},
plugins: [sveltekit()],
build: {
minify: 'terser',
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
}
},
rollupOptions: {
output: {
manualChunks: (id) => {
// Separate large dependencies into their own chunks
if (id.includes('node_modules')) {
if (id.includes('chart.js')) {
return 'chart';
}
if (id.includes('@auth/sveltekit')) {
return 'auth';
}
}
}
}
}
}
});