Skip to content

Respect custom image services for Cloudflare build-time generation (compile + custom)#17099

Open
adamchal wants to merge 6 commits into
withastro:mainfrom
adamchal:cloudflare-compile-respect-image-service
Open

Respect custom image services for Cloudflare build-time generation (compile + custom)#17099
adamchal wants to merge 6 commits into
withastro:mainfrom
adamchal:cloudflare-compile-respect-image-service

Conversation

@adamchal

@adamchal adamchal commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

Changes

  • Keeps a user-configured image.service when the Cloudflare adapter is using imageService: 'compile', so custom getURL() and getHTMLAttributes() hooks are used while prerendering markup in workerd.
  • Loads the configured custom service during the Node-side image generation pass, so custom transform() hooks are used for generated image assets.
  • Extends imageService: 'custom' to also generate optimized image assets at build time, mirroring compile. It runs the configured image.service (or Astro's default Sharp service when none is set) during the Node-side generation pass, while continuing to use the configured service for runtime image handling.
imageService user image.service Before After
'compile' none (default Sharp) Workerd-safe service for prerendered markup; Sharp on the Node side for generation; Sharp-free worker bundle. Unchanged.
'compile' custom Replaced the custom service with the workerd-safe service, so custom markup and transform() hooks were skipped. Preserves the custom service for prerendered markup and runs its transform() hook during image generation.
'custom' none (default Sharp) No build-time asset generation; the default Sharp service is bundled into the worker (where it cannot run). Generates assets with Sharp on the Node side. Runtime bundle unchanged — the default Sharp service is still bundled (and remains Workers-incompatible), per the documented custom tradeoff.
'custom' custom No build-time asset generation; the custom service was used only at runtime. Generates assets with the custom service at build time and continues to use it for runtime image handling.
'cloudflare' | 'cloudflare-binding' | 'passthrough' Existing adapter behavior for those modes. Unchanged.

The compile rows also cover the compound form imageService: { build: 'compile', runtime: ... }.

Testing

  • Reworks the Cloudflare compile image service test coverage into a build-time generation matrix that exercises both imageService: 'compile' and imageService: 'custom' across three service configurations: no user service (Astro's default Sharp service), a Sharp-free custom service, and a Sharp-backed custom service. Each cell asserts:
    • hashed _astro/*.webp assets are generated at build time (real WEBP bytes, or the custom transform() marker for the Sharp-free user service);
    • custom getHTMLAttributes() markup is preserved;
    • the worker bundle deps match each mode's contract: compile stays Sharp-free (Sharp runs only on the Node side); custom reflects its configured runtime service — clean for a Sharp-free user service, but dragging Sharp in for both a Sharp-backed user service and the no-image.service default.

Docs

  • The Cloudflare adapter guide could be updated to mention that the 'compile' mode “uses image.service, if defined otherwise a combination of internal dependencies to transform images locally at build time for prerendered routes.” And it could also mention that 'custom' will do the same thing during build time. But, it may not be necessary—I feel like this is what I expected to be the case. Happy to draft a withastro/docs PR.
  • Draft docs PR Update Cloudflare imageService docs for custom image service support docs#14095

Related PRs

  • This is related to Add opt-in Cloudflare binding image optimization during build #16194, which adds an opt-in compound { build: 'cloudflare-binding' } mode so the Cloudflare Images binding transforms prerendered images during the build (writing optimized bytes directly, falling back to Sharp); this PR keeps local image-service generation paths working with custom image services and brings build-time generation to custom mode. The behaviors should compose: compile and custom respect custom local image services, while the opt-in cloudflare-binding build mode uses the Images binding.

Closes #16201

@changeset-bot

changeset-bot Bot commented Jun 16, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1882dcb

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

This PR includes changesets to release 40 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-cache-provider Patch
@test/astro-cloudflare-client-address Patch
@test/astro-cloudflare-compile-custom-image-service 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/astro-cloudflare-prerenderer-render-error 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 Jun 16, 2026
Comment thread .changeset/cloudflare-compile-respect-image-service.md Outdated
Co-authored-by: Emanuele Stoppa <my.burning@gmail.com>
@matthewp

Copy link
Copy Markdown
Contributor

We have the 'custom' option already. Why does that not work for you?

@matthewp matthewp left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Want to understand why 'custom' doesn't work for them, would prefer to keep the image config simple if possible.

@adamchal

Copy link
Copy Markdown
Contributor Author

'custom' handles the “do not override my service” part, but it does not enable the compile-time output path.

Currently, 'compile' is the only available build-time option

From docs and true in index.ts#L470.

I considered making the change to 'custom', but that would be a breaking behavior change and could pull Node-only image service deps into the worker bundle.

@adamchal adamchal changed the title Respect custom image services in Cloudflare compile mode Jun 18, 2026
@adamchal

Copy link
Copy Markdown
Contributor Author

@matthewp you were right: there isn’t really a good reason to prevent imageService: 'custom' from doing build-time asset generation. It shouldn’t be a regression for anyone.

The actual caveat with custom is runtime compatibility: if the configured image.service pulls in Sharp or other Node-only deps, those will end up in the Worker bundle. I had thought avoiding build-time generation was what prevented that, but that was wrong. The hazard already exists today if custom points at an image service that isn’t workerd-safe.

I updated the PR to let custom participate in build-time asset generation, like you suggested. I’m not sure if this warrants a withastro/docs update, but I can draft some changes if you think it should.

@matthewp

Copy link
Copy Markdown
Contributor

@adamchal great! Code looks good. Yeah we do need a docs update just because the signature changed.

@adamchal

Copy link
Copy Markdown
Contributor Author

Drafted a docs PR withastro/docs#14095. Thanks for the guidance @matthewp!

@matthewp

Copy link
Copy Markdown
Contributor

Haven't forgotten about this one. Hope to get it in soon.

Comment thread .changeset/cloudflare-compile-respect-image-service.md Outdated
@matthewp

Copy link
Copy Markdown
Contributor

This is ready, pending the changeset change.

@matthewp

matthewp commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Also closes #16035

Co-authored-by: Armand Philippot <git@armand.philippot.eu>

@ArmandPhilippot ArmandPhilippot 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.

Thanks, LGTM docs-wise!

I also added #16035 to the "Development" section. This may be due to the non-capitalization of "closes" in Matthew's post, but it was not added automatically.

@github-actions github-actions Bot added the pkg: astro Related to the core `astro` package (scope) label Jul 1, 2026
@matthewp matthewp force-pushed the cloudflare-compile-respect-image-service branch from a59786d to 09cd4c1 Compare July 1, 2026 13:50
@codspeed-hq

codspeed-hq Bot commented Jul 1, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 18 untouched benchmarks


Comparing adamchal:cloudflare-compile-respect-image-service (09cd4c1) with main (9c05ba4)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (02b73b0) during the generation of this report, so 9c05ba4 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

pnpm v11 skips the current-platform optional native binary
(@img/sharp-win32-x64) on the Windows runner, so sharp fails to load
during build-time image generation. Force-install the @img/sharp-*
binaries for all CI OS/CPU targets via supportedArchitectures.
@matthewp matthewp force-pushed the cloudflare-compile-respect-image-service branch from 09cd4c1 to 1882dcb Compare July 1, 2026 15:12
@github-actions github-actions Bot removed the pkg: astro Related to the core `astro` package (scope) label Jul 1, 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)

4 participants