Skip to content

fix(cloudflare): inject headers for caching the assets folder#16571

Merged
florian-lefebvre merged 14 commits into
withastro:mainfrom
MA2153:fix-cf-asset-cache
Jun 8, 2026
Merged

fix(cloudflare): inject headers for caching the assets folder#16571
florian-lefebvre merged 14 commits into
withastro:mainfrom
MA2153:fix-cf-asset-cache

Conversation

@MA2153

@MA2153 MA2153 commented May 2, 2026

Copy link
Copy Markdown

Fixes #16692

Changes

  • Automatically injects Cache-Control: public, max-age=31536000, immutable for hashed Astro assets (/_astro/*) into Cloudflare's _headers file at build time, so browsers cache assets across deploys without extra user configuration.
  • Skips injection when build.assetsPrefix is set (assets are served from a different origin).
  • Skips injection when the user's existing _headers already has a Cache-Control rule whose URL pattern matches the assets path — Cloudflare merges duplicate matching rules' headers with a comma, which would produce contradictory cache directives.
  • Respects base config: the injected pattern is prefixed accordingly (e.g. /blog/_astro/*).
  • Injection block is prepended before any existing user-defined headers so rule ordering in the file is predictable.
  • Atomic _headers write (write to .tmp, then rename) to avoid leaving the file truncated on a mid-write crash.

Testing

  • Added unit tests for the new headersFileHasCacheControlForPath utility in packages/integrations/cloudflare/test/headers.test.ts, covering: empty files, exact patterns, global splat (/*), ! Cache-Control detach, non-matching rules, placeholder patterns (:name), host-prefixed patterns, comments/blank lines, base-prefixed paths, and case-insensitivity.
  • Extended the existing with-base integration test to assert the injected block is present with the correct base prefix, that user-defined headers are preserved, and that the injected block is placed before user headers.

Docs

No documentation changes needed — this is an internal build-time improvement for Cloudflare deployments. The behavior is automatic and the skip conditions (logged via logger.info) are observable in build output. No new configuration options were added.

Other Info

Live preview of the fix: https://with-fix-astro-assets-cf-repro.ma2153.workers.dev/

@changeset-bot

changeset-bot Bot commented May 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c48d4f0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 37 packages
Name Type
@astrojs/cloudflare Minor
@test/astro-cloudflare-node-prerender-mdx Patch
@test/astro-cloudflare Patch
@test/astro-cloudflare-allowed-hosts Patch
@test/astro-cloudflare-astro-dev-platform Patch
@test/astro-cloudflare-astro-env Patch
@test/astro-cloudflare-binding-image-service Patch
@test/astro-cloudflare-cache-provider-wait-until Patch
@test/astro-cloudflare-client-address Patch
@test/astro-cloudflare-compile-image-service Patch
@test/astro-cloudflare-custom-entryfile Patch
@test/astro-cloudflare-dev-image-endpoint Patch
@test/astro-cloudflare-external-image-service Patch
@test/astro-cloudflare-external-redirects Patch
@test/astro-cloudflare-internal-redirects Patch
@test/astro-cloudflare-no-output Patch
@test/astro-cloudflare-prerender-node-env Patch
@test/astro-cloudflare-prerender-queue-consumers Patch
@test/astro-cloudflare-prerender-styles Patch
@test/astro-cloudflare-prerenderer-errors Patch
@test/routing-priority-cloudflare Patch
@test/cf-server-entry Patch
@test/astro-cloudflare-server-island-prerender-framework Patch
@test/astro-cloudflare-sessions Patch
@test/astro-cloudflare-sql-import Patch
@test/cf-ssr-deps Patch
@test/astro-cloudflare-static Patch
@test/astro-cloudflare-svelte-rune-deps Patch
@test/astro-cloudflare-top-level-return Patch
@test/cf-user-optimize-deps Patch
@test/astro-cloudflare-vite-plugin Patch
@test/astro-cloudflare-with-base Patch
@test/astro-cloudflare-with-react Patch
@test/astro-cloudflare-with-solid-js Patch
@test/astro-cloudflare-with-svelte Patch
@test/astro-cloudflare-with-vue Patch
@test/astro-cloudflare-wrangler-preview-platform Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions github-actions Bot added the pkg: integration Related to any renderer integration (scope) label May 2, 2026
@MA2153 MA2153 changed the title Fix cf asset cache fix(cloudflare): Inject headers for caching the assets folder May 2, 2026
@MA2153 MA2153 changed the title fix(cloudflare): Inject headers for caching the assets folder fix(cloudflare): inject headers for caching the assets folder May 2, 2026
@MA2153 MA2153 force-pushed the fix-cf-asset-cache branch from 8b568f9 to 32acd0e Compare May 10, 2026 20:59

@ematipico ematipico left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking because it's unclear what this PR does. It it's fixing a bug, there should be at least a reproduction and the PR should explain the fix, not "the changes"

@florian-lefebvre

Copy link
Copy Markdown
Member

This brings the Cloudflare adapter to parity with other official adapters. Unfortunately it's more complicated because CF doesn't have a nicer way for us to provide headers

@florian-lefebvre florian-lefebvre left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it looks pretty good! Ideally it should only include unit tests to speed things up. Do you think you could update the PR to do that? That likely requires extracting the whole logic to a dedicated function so it can be tested in isolation (and accepting some things like readFile) as arguments. See https://github.com/withastro/astro/blob/main/CONTRIBUTING.md#making-code-testable

Comment thread .changeset/fix-cf-asset-cache-headers.md Outdated
MA2153 and others added 2 commits May 18, 2026 10:37
Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>
@MA2153

MA2153 commented May 18, 2026

Copy link
Copy Markdown
Author

@florian-lefebvre Good idea! Just did,

@MA2153 MA2153 requested a review from florian-lefebvre May 18, 2026 07:58

@florian-lefebvre florian-lefebvre left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM thanks!

Comment thread .changeset/fix-cf-asset-cache-headers.md Outdated
@florian-lefebvre

Copy link
Copy Markdown
Member

@ematipico can you have another look?

Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>

@ematipico ematipico left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably put more emphasis in the changeset

Comment thread .changeset/fix-cf-asset-cache-headers.md
Co-authored-by: Florian Lefebvre <contact@florian-lefebvre.dev>
@MA2153 MA2153 requested a review from ematipico May 18, 2026 12:42
@florian-lefebvre

Copy link
Copy Markdown
Member

@MA2153 can you resolve the conflicts?

# Conflicts:
#	packages/integrations/cloudflare/src/index.ts
#	packages/integrations/cloudflare/test/with-base.test.ts
@MA2153

MA2153 commented Jun 8, 2026

Copy link
Copy Markdown
Author

@florian-lefebvre Done

@florian-lefebvre florian-lefebvre merged commit d4b0cd1 into withastro:main Jun 8, 2026
24 checks passed
This was referenced Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pkg: integration Related to any renderer integration (scope)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cloudflare Integration Does Not Cache Hashed Assets

3 participants