diff --git a/.changeset/breezy-walls-stare.md b/.changeset/breezy-walls-stare.md new file mode 100644 index 000000000..a96847033 --- /dev/null +++ b/.changeset/breezy-walls-stare.md @@ -0,0 +1,5 @@ +--- +'@cloudflare/next-on-pages': patch +--- + +Fix autogenerated content also getting appended to the original public/\_headers file diff --git a/packages/next-on-pages/src/buildApplication/buildMetadataFiles.ts b/packages/next-on-pages/src/buildApplication/buildMetadataFiles.ts index a84683b68..bfa273c1d 100644 --- a/packages/next-on-pages/src/buildApplication/buildMetadataFiles.ts +++ b/packages/next-on-pages/src/buildApplication/buildMetadataFiles.ts @@ -1,5 +1,5 @@ import { join } from 'path'; -import { writeFile } from 'fs/promises'; +import { writeFile, stat, unlink, readFile } from 'fs/promises'; import { nextOnPagesVersion, readJsonFile } from '../utils'; import { getPhaseRoutes, getVercelConfig } from './getVercelConfig'; import { cliError } from '../cli'; @@ -40,22 +40,37 @@ async function buildNextStaticHeaders( ); const nextStaticHeaders = (nextStaticRoute as VercelSource)?.headers; - if (nextStaticHeaders) { - await writeFile( - join(outputDir, '_headers'), - ` + if (!nextStaticHeaders) { + return; + } + + const headersPath = join(outputDir, '_headers'); + + const nopContent = ` # === START AUTOGENERATED @cloudflare/next-on-pages IMMUTABLE HEADERS === ${nextStaticPath}/* ${Object.entries(nextStaticHeaders) .map(([header, value]) => ` ${header}: ${value}`) .join('\n')} -# === END AUTOGENERATED @cloudflare/next-on-pages IMMUTABLE HEADERS ===\n`, - { - // in case someone configured redirects already, append to the end - flag: 'a', - }, - ); +# === END AUTOGENERATED @cloudflare/next-on-pages IMMUTABLE HEADERS ===\n`; + + try { + // Vercel hard links the static files directory: + // https://github.com/vercel/vercel/blob/8e20fed/packages/cli/src/util/build/write-build-result.ts#L336 + // So we need to unlink before we append data, otherwise we will mutate + // the original file found in the public directory. + const stats = await stat(headersPath); + if (stats.nlink > 1) { + const data = await readFile(headersPath); + await unlink(headersPath); + await writeFile(headersPath, data); + } + } catch (e) { + if ((e as { code?: string }).code !== 'ENOENT') { + throw e; + } } + await writeFile(headersPath, nopContent, { flag: 'a' }); } /**