Skip to content

fix: resolve island CSS paths and deploy compat flag mismatch - #71

Merged
Brooooooklyn merged 1 commit into
mainfrom
fix/deploy-compat-and-island-css
Apr 3, 2026
Merged

Brooooooklyn merged 1 commit into
mainfrom
fix/deploy-compat-and-island-css

Conversation

@Brooooooklyn

@Brooooooklyn Brooooooklyn commented Apr 3, 2026 •

Copy link
Copy Markdown
Member

Control flow analysis

Build time (works)

  1. User runs void deploy from playground/react-pages/
  2. The CLI shells out to vite build, which invokes @cloudflare/vite-plugin
  3. The plugin builds two environments: client (browser JS) and ssr (worker bundle)
  4. During the SSR build, the virtual renderer module is generated:
    import React from "react";
    import { renderToString } from "react-dom/server";
    import { SharedContext, ErrorsContext, RouterContext } from "@void/react";
  5. @void/react is a pre-built npm package whose dist imports { createContext, useContext } from "react"
  6. Rolldown bundles everything into a module graph under dist/ssr/ -- index.js + assets/*.js chunks
  7. React ends up in a single CJS-wrapped chunk (react-BVLPaBiV.js) shared by all consumers. No dual React.
  8. @cloudflare/vite-plugin writes dist/ssr/wrangler.json with compatibility_flags: ["nodejs_als"] and compatibility_date: "2026-03-29"

Deploy packaging (the first bug)

  1. The CLI calls readWranglerCompat(root, config) to get compat settings for the deploy manifest
  2. It looks for wrangler.json at the project root (playground/react-pages/) -- does not exist
  3. It looks for worker.compatibility_flags in void.json -- not set
  4. Falls back to hardcoded defaults: compatibility_date: "2026-02-12", compatibilityFlags: undefined
  5. The build output's dist/ssr/wrangler.json (which has the correct settings) is never read
  6. The CLI packages all worker files from dist/ssr/ into a FormData with the manifest
  7. The manifest has compatibilityFlags: undefined

Server-side deploy (the second bug)

  1. The platform API (packages/api/src/routes/deploy.ts) receives the FormData
  2. It builds WfP upload metadata:
    compatibility_flags: manifest.compatibilityFlags ?? ["nodejs_compat"]
  3. Since manifest.compatibilityFlags is undefined, the fallback ["nodejs_compat"] kicks in
  4. The worker is uploaded to Workers for Platforms with:
    • compatibility_flags: ["nodejs_compat"] (wrong -- should be ["nodejs_als"])
    • compatibility_date: "2026-02-12" (wrong -- should be "2026-03-29")

Runtime (the crash)

  1. A request hits https://void-test-it.void.app/
  2. The dispatch worker (packages/dispatch) routes it to the user's WfP worker
  3. The worker's index.js entry handles the request via Hono
  4. The route handler calls handlePageGet(...) which calls renderPage(pageObj, assetTags)
  5. The virtual renderer builds the React element tree:
    element = React.createElement(SharedContext.Provider, { value: shared },
      React.createElement(ErrorsContext.Provider, { value: errors },
        React.createElement(RouterContext.Provider, { value: null },
          React.createElement(Layout, null,
            React.createElement(HomePage, props)))))
  6. It calls renderToString(element) -- this enters React's server renderer
  7. React's server renderer sets ReactSharedInternals.H = serverDispatcher and begins rendering
  8. The Layout component runs, calls useShared() -> useContext(SharedContext)
  9. useContext internally does ReactSharedInternals.H.useContext(context)
  10. Under nodejs_compat at compat date 2026-02-12 on WfP, ReactSharedInternals.H is null at this point -- the dispatcher set by renderToString is not visible to the useContext call
  11. null.useContext -> TypeError: Cannot read properties of null (reading 'useContext')
  12. The worker returns 500

Why it works locally

  • vite dev: No bundling. @void/react is excluded from dep optimization (optimizeDeps.exclude), so all code shares the same live React module. nodejs_als is used by the Cloudflare plugin's dev server.
  • wrangler dev on build output: Reads dist/ssr/wrangler.json directly, which has the correct nodejs_als flag and 2026-03-29 date. The local workerd runtime evaluates modules correctly under these settings.

The fix

The deploy pipeline now reads the build output's wrangler.json as a fallback source for compat settings (priority: void.json > project wrangler.json > build output wrangler.json > hardcoded default). This ensures the deployed worker runs with the same flags the build was designed for.

Also fixes a separate build failure where island CSS imports with relative paths (e.g. import "./global.css" in a layout) were copied verbatim into the virtual islands-client entry module, where they could not resolve. Now rewrites them to absolute paths.

Copy link
Copy Markdown
Member Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@Brooooooklyn
Brooooooklyn requested a review from cpojer April 3, 2026 03:32
@Brooooooklyn
Brooooooklyn marked this pull request as draft April 3, 2026 03:32

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment thread packages/react/src/plugin-islands.ts Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7a4b379e38

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/void/src/cli/deploy.ts Outdated
Two fixes:

1. Island CSS build failure: the island client entry extracted CSS imports
   from page/layout files verbatim (e.g. `import "./global.css"`), but
   relative paths don't resolve from the virtual module. Now resolves
   relative specifiers to absolute paths (with normalizePath for Windows)
   via a shared rewriteCssImportForVirtualModule helper. Affects all four
   adapter packages (react, vue, svelte, solid).

2. Deploy compat flag mismatch: the deploy CLI read compatibility settings
   from the project root's wrangler.json (which typically doesn't exist for
   void apps), falling back to `nodejs_compat` with an old compat date.
   But the build output's wrangler.json (generated by @cloudflare/vite-plugin)
   specifies `nodejs_als` with the correct date. Now falls back to the build
   output's settings before using hardcoded defaults. Uses the original
   workerDir (not actualWorkerDir) in framework deploys so bundleEntry()
   temp dirs don't shadow the plugin-generated config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Brooooooklyn
Brooooooklyn force-pushed the fix/deploy-compat-and-island-css branch from 1ef5f54 to 0da594e Compare April 3, 2026 04:07
@Brooooooklyn
Brooooooklyn marked this pull request as ready for review April 3, 2026 04:07
@Brooooooklyn
Brooooooklyn merged commit ce60d48 into main Apr 3, 2026
7 checks passed
@Brooooooklyn
Brooooooklyn deleted the fix/deploy-compat-and-island-css branch April 3, 2026 05:07
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.

1 participant