From 173d9d138d67eddaec225132b05b72f08dae6512 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 21 Apr 2026 13:08:53 +0200 Subject: [PATCH] fix(ai): sharp via createRequire, nicht ES-Import ES-Dynamic-Import mit @vite-ignore reichte nicht -- adapter-node's Rollup-Step extrahiert sharp trotzdem in einen shared chunk und bundelt sharp's interne dynamic-requires kaputt. createRequire(import.meta.url) plus require('sharp') ist pure Node- Runtime-Logik, die Rollup komplett ignoriert. sharp wird regulaer aus node_modules geladen -- inkl. seiner Plattform-.node-Binary aus @img/sharp-linuxmusl-arm64. Verifikation: Build-Output enthaelt 0 Vorkommen von "dynamicRequireTargets" und "sharp.node" (waren vorher in einem 319KB shared chunk). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/lib/server/ai/image-preprocess.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/lib/server/ai/image-preprocess.ts b/src/lib/server/ai/image-preprocess.ts index f69a91f..62474f0 100644 --- a/src/lib/server/ai/image-preprocess.ts +++ b/src/lib/server/ai/image-preprocess.ts @@ -1,4 +1,5 @@ import type SharpType from 'sharp'; +import { createRequire } from 'node:module'; const MAX_EDGE = 1600; const JPEG_QUALITY = 85; @@ -8,20 +9,25 @@ export type PreprocessedImage = { mimeType: 'image/jpeg'; }; -// Dynamic import: adapter-node bundelt server-code via Rollup/@rollup/plugin-commonjs, -// und das packt sharp's dynamic-require fuer die native Plattform-.node-Binary -// kaputt ins Bundle. Mit import() via Vite's Hint-Kommentar kann Rollup sharp -// nicht auflösen und laesst es zur Laufzeit regulaer aus node_modules laden. -async function loadSharp(): Promise { - const mod = await import(/* @vite-ignore */ 'sharp'); - return (mod as unknown as { default: typeof SharpType }).default ?? (mod as unknown as typeof SharpType); +// sharp per Node-Runtime-require laden, nicht via ES-Import: adapter-node +// bundelt ES-Imports (auch dynamische, auch mit @vite-ignore) ins Server- +// Bundle, was sharp's internes dynamic-require fuer die Plattform-.node-Binary +// zerstoert. createRequire + require() ist pure Node-Runtime-Logik, die +// Rollup nicht anfasst -- sharp wird regulaer aus node_modules geladen. +const nodeRequire = createRequire(import.meta.url); +let sharpModule: typeof SharpType | null = null; +function loadSharp(): typeof SharpType { + if (!sharpModule) { + sharpModule = nodeRequire('sharp') as typeof SharpType; + } + return sharpModule; } // Resize auf max 1600px lange Kante, JPEG re-encode, Metadata strippen. // sharp liest HEIC/HEIF transparent, wenn libheif im libvips-Build enthalten ist // (in Alpine's vips-dev + in den offiziellen sharp-Prebuilds). export async function preprocessImage(input: Buffer): Promise { - const sharp = await loadSharp(); + const sharp = loadSharp(); const pipeline = sharp(input, { failOn: 'error' }).rotate(); // respect EXIF orientation const meta = await pipeline.metadata(); if (!meta.width || !meta.height) {