Skip to content

fix(cloudflare): enable Sharp image optimization for default cloudflare-binding mode#16194

Open
Desel72 wants to merge 4 commits intowithastro:mainfrom
Desel72:fix/issue-16035
Open

fix(cloudflare): enable Sharp image optimization for default cloudflare-binding mode#16194
Desel72 wants to merge 4 commits intowithastro:mainfrom
Desel72:fix/issue-16035

Conversation

@Desel72
Copy link
Copy Markdown
Contributor

@Desel72 Desel72 commented Apr 2, 2026

The default cloudflare-binding image service relied on the IMAGES binding for transforms, but this binding is unavailable during the Node-side build pipeline. Prerendered pages were left with un-optimized images. Expand the Sharp fallback to cover both compile and cloudflare-binding build services so that static images are optimized at build time.

Fixes #16035

Changes

  • Added needsBuildTimeOptimization flag that covers both compile and cloudflare-binding build services
  • compileImageConfig is now passed to the workerd prerender handler for cloudflare-binding, enabling installAddStaticImage to track images during prerendering
  • collectStaticImages is now defined for cloudflare-binding, allowing Sharp to process tracked images on the Node side during build
  • Added changeset for @astrojs/cloudflare patch

Before: Default cloudflare-binding mode skipped build-time image optimization entirely — prerendered/static pages contained un-optimized images.

After: Sharp processes images at build time for both compile and cloudflare-binding modes, producing optimized output.

Testing

All 136 existing Cloudflare adapter tests pass with 0 failures, including:

  • compile-image-service.test.js (5/5 pass)
  • binding-image-service.test.js (6/6 pass)
  • external-image-service.test.js (2/2 pass)
  • dev-image-endpoint.test.js (6/6 pass)
  • prerenderer-errors.test.js (1/1 pass)
  • static.test.js (1/1 pass)

Reproduction repo: https://github.com/alexanderniebuhr/astro-v6-repro

Docs

No docs changes needed. This fix aligns the default cloudflare-binding behavior with what users already expect — image optimization should work out of the box. The existing Cloudflare adapter docs describe cloudflare-binding as the default image service; this change ensures it actually optimizes images at build time.

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 2, 2026

🦋 Changeset detected

Latest commit: 64358fe

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

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 Apr 2, 2026
Copy link
Copy Markdown
Member

@alexanderniebuhr alexanderniebuhr left a comment

Choose a reason for hiding this comment

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

I'm not sure if this is correct. In theory the image binding should have sharp for prerender optimization. And the binding should be available when workerd is used for prerendering.

cc @OliverSpeir @Princesseuh who might have more context to share

@OliverSpeir
Copy link
Copy Markdown
Contributor

Cloudflare-binding intentionally does not transform images on pre-rendered routes locally during build. The intention is they go to the image endpoint at request time as well, one benefit of this is faster build times

@alexanderniebuhr
Copy link
Copy Markdown
Member

alexanderniebuhr commented Apr 2, 2026

It should use the cloudflare binding itself to optimize them during build time though, not sharp. So like during workerd prerendering the image endpoint should be requested, which then uses cloudflare's own binding to optimize the images.

@alexanderniebuhr
Copy link
Copy Markdown
Member

@Desel72 I'm sorry, but we are still discussing if this is actually an bug or the expected behavior on Discord. So we might end up not merging this, but no decision yet.

@Desel72
Copy link
Copy Markdown
Contributor Author

Desel72 commented Apr 2, 2026

Thank you for the context, @alexanderniebuhr! I think I misunderstood the design intent behind cloudflare-binding. If the decision is that build-time optimization should happen for prerendered routes, I think the correct approach would be to have the workerd prerender worker call the image transform endpoint (which uses the IMAGES binding) during the build phase, rather than falling back to Sharp on the Node side. Happy to rework the approach if it turns out to be a bug that needs fixing. I think this should be fixed.

@alexanderniebuhr
Copy link
Copy Markdown
Member

If the decision is that build-time optimization should happen for prerendered routes, I think the correct approach would be to have the workerd prerender worker call the image transform endpoint

@Desel72 yeah after discussion we think this the the better way. I'll update the original issue so it makes more sense. Would you like to still work on that? If so, do you want to use this PR or should we close it and you can create a new one?

@Desel72
Copy link
Copy Markdown
Contributor Author

Desel72 commented Apr 4, 2026

I'd love to use this PR @alexanderniebuhr I will solve perfectly.

… in cloudflare-binding mode (withastro#16035)

When using the default `cloudflare-binding` image service, prerendered pages
had un-optimized images because the IMAGES binding was only used at runtime.
Now during the build, `handleStaticImagesRequest` uses the IMAGES binding in
workerd to transform images, and the optimized bytes are written directly to
the output directory. Falls back to Sharp if the binding is unavailable.
@Desel72
Copy link
Copy Markdown
Contributor Author

Desel72 commented Apr 6, 2026

Hi @matthewp @alexanderniebuhr I've done. Welcome to your feedback. Thanks

@alexanderniebuhr
Copy link
Copy Markdown
Member

@Desel72 we are going to review the PR as soon as we have bandwidth, but please fix the failing lint check :)

@Desel72
Copy link
Copy Markdown
Contributor Author

Desel72 commented Apr 8, 2026

@alexanderniebuhr Thanks for your reviewing. I've solved.

@Desel72
Copy link
Copy Markdown
Contributor Author

Desel72 commented Apr 10, 2026

Hi @alexanderniebuhr is there any update on this PR?

@alexanderniebuhr
Copy link
Copy Markdown
Member

We are still reviewing this. Current state is that this should be put behind a option, so users can opt-in and opt-out and the changeset can't be a patch, since it's a breaking change.

Copy link
Copy Markdown
Member

@alexanderniebuhr alexanderniebuhr left a comment

Choose a reason for hiding this comment

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

Please make sure that this is a major change, which means we need to update the changeset as well as have an docs PR. The behavior should also put behind a flag so users can opt-in or opt-out. I suggest using the triplet configuration suggested here: #15662

uni added 2 commits April 19, 2026 23:35
…pt-in config

Per maintainer feedback, the new behavior is now opt-in via the compound
`{ build: 'cloudflare-binding', runtime: 'cloudflare-binding' }` config.
The string shorthand `'cloudflare-binding'` preserves the historical
runtime-only behavior and is unaffected.

- Extend ImageServiceConfig type with a second compound form for `cloudflare-binding`
- Add `transformAtBuild` flag returned from normalizeImageServiceConfig
- Bump changeset from patch to minor since this adds a new config option
@Desel72
Copy link
Copy Markdown
Contributor Author

Desel72 commented Apr 19, 2026

Please make sure that this is a major change, which means we need to update the changeset as well as have an docs PR. The behavior should also put behind a flag so users can opt-in or opt-out. I suggest using the triplet configuration suggested here: #15662

Hi @alexanderniebuhr, how are you? Sorry for the late. I've solved this. Please review this.

@Desel72
Copy link
Copy Markdown
Contributor Author

Desel72 commented Apr 19, 2026

@alexanderniebuhr
For the docs PR, two options — which do you prefer?
-I open it now at withastro/docs
-I wait until the config shape is finalized here
Also let me know if the triplet should include dev too (full { build, dev, runtime } from #15662).

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.

image optimization using cloudflare-binding does not optimize during build time

3 participants