diff --git a/apps/web/css-stub-loader.mjs b/apps/web/css-stub-loader.mjs index 2f61484..b2ea207 100644 --- a/apps/web/css-stub-loader.mjs +++ b/apps/web/css-stub-loader.mjs @@ -1,33 +1,10 @@ -/** - * Node.js ESM custom loader — stubs static asset imports as empty modules. - * - * Next.js 16 does route collection in raw Node ESM (not webpack/turbopack). - * Payload CMS deps import .css, .scss, .svg, and other assets that Node - * can't handle. This loader intercepts those and returns empty modules. - * - * Usage: NODE_OPTIONS="--import ./apps/web/css-stub-loader.mjs" - */ - -import { register } from "node:module"; - -register( - "data:text/javascript," + - encodeURIComponent(` -const STYLE_RE = /\\.(css|scss|sass|less|svg|png|jpg|jpeg|gif|webp|ico|woff|woff2|ttf|eot|otf)$/; +// Node.js ESM loader that stubs non-JS asset imports during Next.js page data collection. +// Payload CMS and its deps import .css/.scss/.svg files that Node.js can't handle. +const STUB_EXTENSIONS = ['.css', '.scss', '.sass', '.svg', '.png', '.jpg', '.jpeg', '.gif', '.ico', '.woff', '.woff2', '.ttf', '.eot']; export function resolve(specifier, context, nextResolve) { - if (STYLE_RE.test(specifier)) { - return { url: 'data:text/javascript,export default {};', shortCircuit: true }; + if (STUB_EXTENSIONS.some(ext => specifier.endsWith(ext))) { + return { url: 'data:text/javascript,export default ""', shortCircuit: true }; } return nextResolve(specifier, context); } - -export function load(url, context, nextLoad) { - if (STYLE_RE.test(url)) { - return { format: 'module', source: 'export default {};', shortCircuit: true }; - } - return nextLoad(url, context); -} -`), - import.meta.url, -); diff --git a/apps/web/next.config.ts b/apps/web/next.config.ts index fd602ac..ffa6b73 100644 --- a/apps/web/next.config.ts +++ b/apps/web/next.config.ts @@ -90,7 +90,6 @@ const config: NextConfig = { "@payloadcms/richtext-lexical", "@payloadcms/next", "@payloadcms/ui", - "react-image-crop", "sharp", "libsodium-wrappers", ], @@ -130,7 +129,7 @@ const config: NextConfig = { }, /** Enables hot reloading for local packages without a build step */ - transpilePackages: INTERNAL_PACKAGES, + transpilePackages: [...INTERNAL_PACKAGES, "react-image-crop"], experimental: { optimizePackageImports: INTERNAL_PACKAGES, }, diff --git a/apps/web/package.json b/apps/web/package.json index b3f56e3..55a5a90 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -4,7 +4,7 @@ "private": true, "type": "module", "scripts": { - "build": "next build --webpack", + "build": "NODE_OPTIONS='--experimental-loader ./css-stub-loader.mjs' next build --webpack", "clean": "git clean -xdf .cache .next .turbo node_modules", "dev": "next dev", "format": "prettier --check . --ignore-path ../../.gitignore",