moonming opened a new pull request, #2064:
URL: https://github.com/apache/apisix-website/pull/2064
## What
Adds a shared Docusaurus **client module** (`config/chunkReload.js`) that
detects a `ChunkLoadError` during client-side navigation and recovers with a
single hard reload. Registered on all four Docusaurus instances: `website`,
`doc`, `blog/en`, `blog/zh`.
## Why — the "first visit 404, works after refresh" bug
Users report that many pages (e.g. `/docs/apisix/plugins/ai-proxy/`,
`/blog/tags/case-studies/`) return a 404 on first visit when navigated to
**from another page**, but load fine after a refresh.
Root cause is **not** a missing page — the server always returns `200` for a
hard load. It is stale code-split chunks after a redeploy:
- The site rebuilds and republishes frequently — **every push to `master`
plus a daily 05:00 UTC cron** (`.github/workflows/deploy.yml`). Each build also
re-pulls upstream docs, so content (and therefore content-hashed chunk
filenames) changes.
- Each build emits new content-hashed JS/CSS chunks, and the publish step
(`actions-gh-pages`, orphan force-push to `asf-site`) **replaces the previous
build wholesale** — old chunk files are deleted.
- A browser still showing an older page holds an older route manifest. When
you click a link, Docusaurus client-side navigation lazy-loads the target
route's chunk **by a hash that no longer exists on the CDN** → `ChunkLoadError`
→ the 404 page renders. A hard refresh re-fetches the page's current HTML
against the live build, so it works.
Evidence: three different `main.<hash>.js` bundles were observed served
concurrently across pages of the live site, confirming multiple builds
coexisting behind the CDN. HTML is cached `max-age=3600` while hashed assets
are `max-age=864000`, and the ASF publish pipeline exposes no per-project
cache-purge/TTL control (`.asf.yaml` `publish:` has no such options), so the
skew window cannot be closed from the deploy side by this project alone.
This is the same recovery pattern already used elsewhere in the ASF
ecosystem for SPA app shells (e.g. `apache/atlas`, `apache/ranger`,
`apache/texera` all reload on `ChunkLoadError`).
## How
`config/chunkReload.js`:
- Listens on `window` `error` and `unhandledrejection`.
- `isChunkLoadError()` matches `error.name === 'ChunkLoadError'` or a
chunk-load message (`Loading chunk … failed`, `Loading CSS chunk … failed`,
`dynamically imported module`).
- On a match, `reloadOnce()` does a single `window.location.reload()`.
- A `sessionStorage` guard (`apisix-chunk-reload-at`, 10s window) prevents a
reload loop when the chunk is genuinely unavailable (e.g. the browser is
offline) — in that case the 404 page is allowed to render instead.
- SSR-safe: all listener wiring is behind `typeof window !== 'undefined'`.
## Test plan
- [x] `node --check` passes on the new module and all four edited configs.
- [x] `require('./config/chunkReload.js')` runs clean under Node (SSR path)
— no `window`, no listeners attached, no throw.
- [x] Unit-checked `isChunkLoadError` against positive cases
(ChunkLoadError, JS/CSS chunk messages, dynamic-import failure) and negative
cases (unrelated `TypeError`, `null`).
- [ ] CI production build of all four instances.
> Note: the real failure mode (a chunk deleted from the CDN after a
redeploy) cannot be reproduced on a local dev server, which never deletes
hashed chunks. Verification here is limited to build validity, SSR-safety, and
detector correctness.
## Notes
This is an in-repo mitigation fully under the project's control. The
root-cause fix — purge the CDN on deploy / shorten HTML TTL, or retain previous
builds' assets so old chunks keep resolving — lives in the ASF publish/Fastly
layer and would benefit all ASF Docusaurus sites; it can be pursued separately
with ASF Infra.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]