[wrangler][vite-plugin] Fix cf builds for root static projects - #15471
edmundhung wants to merge 3 commits into
Conversation
🦋 Changeset detectedLatest commit: 283a5fc The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
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 |
|
LGTM |
@cloudflare/autoconfig
@cloudflare/build-output-utils
@cloudflare/codemods
@cloudflare/config
@cloudflare/containers-shared
create-cloudflare
@cloudflare/deploy-helpers
@cloudflare/kv-asset-handler
miniflare
@cloudflare/pages-functions
@cloudflare/pages-shared
@cloudflare/unenv-preset
@cloudflare/vite-plugin
@cloudflare/vitest-plugin
@cloudflare/workers-auth
@cloudflare/workers-editor-shared
@cloudflare/workers-utils
wrangler
commit: |
|
Codeowners approval required for this PR:
Show detailed file reviewers |
workers-devprod
left a comment
There was a problem hiding this comment.
Codeowners reviews satisfied
a3502ef to
4cc76c9
Compare
Add a shared asset writer for the Build Output Specification. Normal asset directories retain recursive copying, while a project-root source excludes the reserved `.cloudflare` directory and preserves files already generated in the output tree. ## write.ts The root-specific branch copies direct children except `.cloudflare`; non-overwriting copies let generated artifacts take precedence when a build tool emits files before public assets are added. Reviewable-Commit-Version: 1
Replace Wrangler's unconditional recursive copy with the shared Build Output writer. Root static projects now omit `.cloudflare` instead of copying the output into itself, while normal asset directories and project-provided `.assetsignore` files retain their existing behavior. ## build-output.ts Wrangler keeps bundle emission local and delegates only static asset copying to the shared utility. Reviewable-Commit-Version: 1
Vite's public-directory copier recurses into the nested Build Output tree when `publicDir` is the project root. Disable that copier only for this configuration, then use Vite's post-build hook to fill in missing public files after generated client output exists. ## config.ts Normal public directories keep Vite's native copy behavior; only the root-public case is redirected. ## build-output.ts The post-build hook works with both the default and custom app builders. The shared writer preserves transformed HTML and other generated output without relying on concurrent bundler-hook timing. Reviewable-Commit-Version: 1
4cc76c9 to
283a5fc
Compare
| // Vite's public directory copier recurses into its nested output when | ||
| // the project root is public. The Build Output plugin copies missing | ||
| // public files after the client build has generated its output. | ||
| clientEnvironment.build.copyPublicDir = false; |
There was a problem hiding this comment.
🟡 Vite 6 root assets disappear
With Vite 6 root assets, copyPublicDir is disabled while the replacement buildApp hook is unsupported. Public files outside generated entries disappear from deployments.
Learn more
Vite 6 does not run the buildApp plugin hook, as documented by the existing hook guard in the config plugin. This assignment disables Vite's only public-directory copy path for every supported Vite version. The replacement copy runs exclusively from the new buildApp hook, so Vite 6 builds retain generated client output but omit other root assets.
Example: A Vite 6 project uses publicDir: "." with index.html and robots.txt. Vite generates the built index.html, but robots.txt is absent from .cloudflare/output/v0/workers/default/assets.
Recommended fix: Add a Vite 6-compatible post-build copy path for this exact root-public case. Keep copyPublicDir disabled to avoid recursion, and ensure the fallback runs after client output generation so force: false preserves generated files.
Was this helpful? React with 👍 or 👎 to provide feedback.
| @@ -0,0 +1,9 @@ | |||
| --- | |||
| "@cloudflare/build-output-utils": patch | |||
There was a problem hiding this comment.
🟡 New export receives patch bump
Publishing writeAssets under a patch bump adds an exported API without the required minor classification. The release metadata understates the package change.
| "@cloudflare/build-output-utils": patch | |
| "@cloudflare/build-output-utils": minor |
Was this helpful? React with 👍 or 👎 to provide feedback.
| buildApp: { | ||
| order: "post", | ||
| async handler(builder) { | ||
| if (!builder.environments.client?.isBuilt) { | ||
| return; | ||
| } | ||
|
|
||
| const { publicDir, root } = ctx.resolvedViteConfig; | ||
| if (publicDir && path.resolve(publicDir) === path.resolve(root)) { | ||
| await writeAssets({ root, sourceDirectory: publicDir }); | ||
| } | ||
| }, |
There was a problem hiding this comment.
Root-level static projects can use the project root as their asset source: Wrangler receives
.from cf autoconfig, while Vite supports the equivalentpublicDir: ".". Both Build Output paths place assets under that same root at.cloudflare/output/v0/workers/default/assets, so their default directory copying recursed into the output itself.Asset writing now lives in
@cloudflare/build-output-utils. Its Build Output-specific rule is narrow: when the source is the project root, copy its direct children except the reserved.cloudflaredirectory; otherwise preserve the existing recursive copy behavior.Wrangler delegates asset copying to that shared writer. The Vite plugin keeps Vite's native public-directory behavior for normal directories, but for the exact root-public case it disables Vite's recursive copier and invokes the shared writer during
renderStart. This runs after Vite prepares the output directory but before generated client files are written, preserving generated-output precedence and supporting custom app builders. This PR does not change.assetsignorepolicy.Note
This is a contribution from an AI agent: Codex, GPT-5.