Skip to content

[Feature] Add Cloudflare Workers adapter for shopify-app-react-router#3160

Open
kayluhb wants to merge 3 commits intoShopify:mainfrom
kayluhb:add-shopify-app-react-router-cloudflare-adapter
Open

[Feature] Add Cloudflare Workers adapter for shopify-app-react-router#3160
kayluhb wants to merge 3 commits intoShopify:mainfrom
kayluhb:add-shopify-app-react-router-cloudflare-adapter

Conversation

@kayluhb
Copy link
Copy Markdown

@kayluhb kayluhb commented Apr 15, 2026

WHY are these changes introduced?

Fixes #3161 (just filed — sorry for the out-of-order; PR was already up when I re-read CONTRIBUTING.md).

@shopify/shopify-app-react-router currently only ships an /adapters/node entry point. Anyone deploying a React Router 7 Shopify app to Cloudflare Workers today has to:

  1. Set the nodejs_compat compatibility flag in wrangler.toml purely so the Node adapter's polyfills load, even though every Shopify SDK code path actually runs on Web standards (fetch, Request/Response, crypto.subtle) that Workers natively supports.
  2. Pay the bundle-size cost of pulling Node shims into a Worker that doesn't need them.
  3. Live with the runtime self-identifying as React Router (Node) in telemetry/logs, which is misleading.

The underlying @shopify/shopify-api package already has /adapters/cf-worker (used by shopify-app-express consumers and tested via miniflare). The wrapper layer is the missing piece — this PR adds it.

WHAT is this pull request doing?

Adds @shopify/shopify-app-react-router/adapters/cloudflare:

  • src/server/adapters/cloudflare/index.ts — imports the existing @shopify/shopify-api/adapters/cf-worker runtime, then sets the runtime string to React Router (Cloudflare Worker). Honours process.env.APP_BRIDGE_URL when nodejs_compat is enabled, and falls back gracefully (try/catch) when process is undefined (Workers without nodejs_compat) — in that case users can still call setAppBridgeUrlOverride directly.
  • src/server/adapters/cloudflare/__tests__/setup-jest.ts — mirrors the node adapter's setup file.
  • src/server/adapters/__tests__/cloudflare-app-bridge-url.test.ts — mirrors the existing node-app-bridge-url.test.ts.
  • src/server/adapters/__tests__/cloudflare-runtime-string.test.ts — verifies the runtime string is set correctly.
  • Changeset entry (minor bump for @shopify/shopify-app-react-router).

No changes to existing files. Rollup auto-discovers adapter directories, so the build picks up the new entry point with no config changes. Package exports map already covers ./adapters/*, so consumers can import via @shopify/shopify-app-react-router/adapters/cloudflare immediately.

Verified locally:

  • pnpm build (rollup + tsc) — emits dist/{esm,cjs,ts}/server/adapters/cloudflare/index.{mjs,js,d.ts} alongside the node adapter.
  • pnpm test — 350 tests pass across 51 suites (2 new tests added).
  • pnpm lint — clean.

Type of change

  • Patch: Bug (non-breaking change which fixes an issue)
  • Minor: New feature (non-breaking change which adds functionality)
  • Major: Breaking change (fix or feature that would cause existing functionality to not work as expected)

Checklist

  • I have used pnpm changeset to create a draft changelog entry (do NOT update the CHANGELOG.md files manually)
  • I have added/updated tests for this change
  • I have documented new APIs/updated the documentation for modified APIs (for public APIs) — README doesn't currently mention adapter selection at all (the existing /adapters/node is undocumented). Happy to add an "Adapters" section to the README in this PR if you'd like, or split it into a follow-up — your call.

Mirrors the structure of the existing /adapters/node, pulling in the
underlying @shopify/shopify-api/adapters/cf-worker runtime so consumers
can deploy to Cloudflare Workers without needing the nodejs_compat flag
just to satisfy the Shopify SDK.

The adapter identifies itself as `React Router (Cloudflare Worker)` and
honours `process.env.APP_BRIDGE_URL` when the runtime exposes it
(nodejs_compat enabled) — otherwise the env-driven override is silently
skipped and users can still call `setAppBridgeUrlOverride` directly.

Tests cover both the runtime string and the App Bridge URL override.
- Add `shopify-app-react-router-server-cloudflare` Jest project that wires
  `src/server/adapters/cloudflare/__tests__/setup-jest.ts`, mirroring the
  existing `-server-node` project and the sibling shopify-app-remix package's
  vercel wiring. Without this, the setup file was dead code and the full
  server test suite was never exercised under the Cloudflare Worker runtime.
  Test count goes from 350 across 3 projects to 679 across 4 projects; all
  pass.
- Narrow the `process.env` try/catch in the cloudflare adapter to only
  swallow `ReferenceError` (the "process is not defined" case on Workers
  without `nodejs_compat`). Any other error — e.g. future validation in
  `setAppBridgeUrlOverride` — is re-thrown instead of silently ignored.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The prior wording implied full independence from `nodejs_compat`. The
adapter does load without it, but the `process.env.APP_BRIDGE_URL`
override path still requires `process` to be defined. Spell out the
caveat and point to `setAppBridgeUrlOverride` as the explicit
alternative so reviewers/users don't hit a surprise.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Cloudflare Workers adapter for shopify-app-react-router

1 participant