Your Cloudflare build passes locally but silently fails in CI
A Vite alias that reached outside the repo root built fine locally but failed on Cloudflare Pages for weeks, while the old bundle kept serving.
The symptom
A React + Vite app (CollageCraft) was deployed on Cloudflare Pages. Locally, npm run build succeeded every single time. The site was live and serving. But new changes never showed up in production. No error in the dashboard jumped out, the site just kept serving an old bundle. For weeks I assumed deploys were slow or cached.
What was actually happening
The app imported a shared library through a Vite alias that pointed at a sibling directory living outside the repo:
// vite.config.ts (the broken setup)
resolve: {
alias: {
'collage-core': path.resolve(__dirname, '../collage-core/src'),
},
}
On my machine, ../collage-core/src existed right next to the app folder, so every local build resolved the import and passed.
Cloudflare Pages does not. It clones only the one repo you connected. There is no sibling ../collage-core on the build server, so the alias resolved to a path that did not exist, the build failed, and Cloudflare kept serving the last bundle that did build, which was weeks old. Because local builds always worked, the failure was invisible from where I was looking.
The fix
Vendor the shared library inside the repo and point the alias at the in-repo copy. Commit a copy of the library at collagecraft/collage-core/, then change the alias to a path that exists on a fresh clone:
// vite.config.ts
resolve: {
alias: {
'collage-core': path.resolve(__dirname, './collage-core'),
},
}
Mirror it in TypeScript so the editor and tsc agree with the bundler:
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"collage-core": ["./collage-core"]
}
}
}
After this, a clean clone (which is all CI ever has) resolved the import, the Cloudflare build went green, and new changes finally shipped.
The lesson
“Works locally” is not “works in CI.” CI clones only your repo, so any import that reaches outside the repo root resolves against files that do not exist on the build server. A silently failing build that keeps serving the old bundle is the default suspect, not an edge case, check the build log for the run you care about before you blame caching.