Verwendung
- Installationsbefehl kopieren und das Quellpaket vor der Installation in der eigenen Agentenumgebung prüfen.
- Benötigte Werkzeuge, Zugangsdaten und Hosts im Original prüfen.
- Eingabe und gewünschtes Ergebnis beschreiben und die Ausgabe mit den Quellen abgleichen.
npx skills add https://github.com/olsonbd/superpowers-antigravity --skill deploying-payload-to-cloudflareVor dem Start
- Die Installation umfasst weder Modellabo noch API-Kontingent oder Dateizugriffsrechte.
- Sterne und Installationen zeigen Aktivität, keine unabhängige Qualitäts- oder Sicherheitsprüfung.
Aus dem Quell-Repository gerendert; Überschriften, Beispiele, Code, Tabellen, Links und Bilder bleiben erhalten.
Deploying Payload CMS to Cloudflare Workers
Overview
Deploying Payload CMS to Cloudflare Workers often hits the 3 MiB bundle size limit and encounters issues with native dependencies like sharp and @vercel/og. This skill provides a proven strategy to overcome these limitations by pruning unused files and patching imports.
When to Use
- Deploying Payload CMS to Cloudflare Workers.
- Encountering "Bundle size exceeds 3 MiB" errors.
- Encountering "Could not resolve" errors for
sharp,resvg.wasm, oryoga.wasm.
The Strategy
- Build: Use
@opennextjs/cloudflareto build the worker. - Prune: Remove the massive
node_modulesdirectory from the output. The worker bundle (handler.mjs) already contains the necessary code (mostly). - Patch: Replace absolute paths to missing native modules (which were in the pruned
node_modules) with an empty module stub.
Risks & Trade-offs
By removing node_modules, you are forcing the Worker to rely 100% on the bundled code.
- Native Modules will fail: Libraries like
sharp(C++ binary) cannot be bundled. They must exist on disk. Removingnode_modulesbreaks them. - Mitigation: Disable features relying on them (e.g.,
images: { unoptimized: true }) or use external services (e.g., Cloudflare Images). - Dynamic Imports may fail: If code uses
await import('some-lib')and that lib wasn't bundled, it will fail at runtime. - Mitigation: Ensure
output: 'standalone'is used, which is good at tracing dependencies. Test critical paths.
Implementation
1. Create build-worker.sh Script
Create a script (e.g., scripts/build-worker.sh) with the following content. This script handles building, pruning, and patching to ensure the worker fits within Cloudflare's limits.
#!/bin/bash
set -e
# 1. Build
# Check if we are being called by OpenNext (which calls 'npm run build' internally)
if [ "$IS_OPENNEXT_BUILD" = "true" ]; then
echo "Running internal Next.js build..."
npm run build:next
exit 0
fi
echo "Building OpenNext worker..."
export IS_OPENNEXT_BUILD=true
npx opennextjs-cloudflare build
# 2. Prune node_modules
# The worker bundle is self-contained enough that we don't need the full node_modules
# But we need to keep some externalized packages like graphql
echo "Pruning node_modules..."
rm -rf .open-next/server-functions/default/node_modules
mkdir -p .open-next/server-functions/default/node_modules
# Copy graphql if it exists, as it's often externalized
if [ -d "node_modules/graphql" ]; then
cp -r node_modules/graphql .open-next/server-functions/default/node_modules/
fi
# 3. Create Empty Stubs
echo "Creating stubs..."
# Stub for WASM modules
echo "export default {};" > .open-next/server-functions/default/empty_wasm.js
# Stub for JS libraries (prettier, sharp, etc.)
echo "export default {};" > .open-next/server-functions/default/empty_lib.js
# 4. Patch handler.mjs
echo "Patching handler.mjs..."
# Detect handler path (CI vs Local structure)
if [ -f ".open-next/server-functions/default/backend/handler.mjs" ]; then
HANDLER_PATH=".open-next/server-functions/default/backend/handler.mjs"
else
HANDLER_PATH=".open-next/server-functions/default/handler.mjs"
fi
if [ ! -f "$HANDLER_PATH" ]; then
echo "Error: $HANDLER_PATH not found!"
exit 1
fi
# Replace absolute paths to WASM files with empty_wasm.js
# Matches both single and double quotes, and optional ?module suffix
perl -pi -e 's|(["'"'"'])[^"'"'"']*node_modules/[^"'"'"']+\.wasm(\?module)?\1|\1./empty_wasm.js\1|g' "$HANDLER_PATH"
# Stub .ttf.bin files (often used by @vercel/og)
perl -pi -e 's|(["'"'"'])[^"'"'"']*node_modules/[^"'"'"']+\.ttf\.bin\1|\1./empty_lib.js\1|g' "$HANDLER_PATH"
# Patch specific problematic libraries (prettier, sharp)
perl -pi -e 's|require\("prettier"\)|require("./empty_lib.js")|g' "$HANDLER_PATH"
perl -pi -e 's|import\("prettier"\)|import("./empty_lib.js")|g' "$HANDLER_PATH"
perl -pi -e 's|require\("sharp"\)|require("./empty_lib.js")|g' "$HANDLER_PATH"
perl -pi -e 's|import\("sharp"\)|import("./empty_lib.js")|g' "$HANDLER_PATH"
# Fix any double-slash issues if they occur
perl -pi -e 's|"/./empty_wasm.js"|"\./empty_wasm.js"|g' "$HANDLER_PATH"
perl -pi -e 's|"/./empty_lib.js"|"\./empty_lib.js"|g' "$HANDLER_PATH"
echo "Build and optimization complete."2. Configure next.config.ts
Alias problematic dependencies to an empty file during the Next.js build to prevent them from bloating the initial bundle or causing build errors.
// next.config.ts
import { withPayload } from "@payloadcms/next/withPayload";
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "standalone",
images: {
unoptimized: true, // Cloudflare handles images via a separate worker or R2
},
webpack: (config) => {
// Alias sharp and @vercel/og to empty to avoid bundling them
config.resolve.alias.sharp = "./empty.js";
config.resolve.alias["@vercel/og"] = "./empty.js";
return config;
},
};
export default withPayload(nextConfig);3. CI/CD Integration
Use Cloudflare's native CI/CD integration by connecting your repository in the Cloudflare Dashboard.
- Build Command:
bash scripts/build-worker.sh(ornpm run build:worker) - Build Output Directory:
.open-next/server-functions/default
Common Mistakes
- Not Pruning: Leaving
node_moduleswill almost always exceed the 3 MiB limit. - Not Patching: The generated
handler.mjswill contain absolute paths to the machine where it was built. These paths will fail at runtime on Cloudflare. - Using `pnpm`:
pnpm's symlinked structure can cause issues with pruning and native module resolution (ERR_DLOPEN_FAILED). Use `npm` for this strategy to ensure a flatnode_modulesstructure and better compatibility with Cloudflare's build environment. - Infinite Loops: If
npm run buildcalls this script, and this script callsnpx opennextjs-cloudflare build, which callsnpm run buildagain, you will get an infinite loop. Ensure you have a re-entry guard (as shown in the script above).

