fix: blank page when javascript is disabled#1426
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
2 Skipped Deployments
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
|
@danielroe , should i reduce the delay to 0 seconds? im concerned that might trigger an infinite loop, though I'm not entirely sure. i've set it to 1 second for now to be safe |
|
cc: @lorypelli |
|
we may need to disable the validator on 200.html on the other hand, I think setting to 0 should be safe. |
📝 WalkthroughWalkthroughAdds a Nitro plugin that registers a render:html hook to modify HTML output during prerendering. When prerender is active and the request path is /200.html, the hook injects a noscript meta refresh tag into the document head. The change also updates Nuxt configuration to disable the HTML validator rule for meta-refresh. Possibly related PRs
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
No actionable comments were generated in the recent review. 🎉 Comment |
server/plugins/fallback-ui.ts
Outdated
| nitroApp.hooks.hook('render:html', (html, { event }) => { | ||
| if (event.path.includes('/200.html')) { | ||
| html.head.push('<noscript><meta http-equiv="refresh" content="0"></noscript>') |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
rg -n "200\.html|render:html|spa|fallback" -SRepository: npmx-dev/npmx.dev
Length of output: 50374
🏁 Script executed:
# Find the fallback-ui.ts file
find . -name "fallback-ui.ts" -type f
# Look for nitro config and SPA setup
find . -name "nuxt.config.*" -o -name "nitro.config.*" | head -20
# Search for 200.html references specifically
rg "200\.html" --type ts --type js -B 2 -A 2Repository: npmx-dev/npmx.dev
Length of output: 1469
🏁 Script executed:
# Read the fallback-ui.ts file completely
cat -n server/plugins/fallback-ui.ts
# Read the isr-fallback.ts module to understand SPA fallback handling
cat -n modules/isr-fallback.ts
# Check nuxt.config.ts for SPA/fallback configuration
rg -A 10 -B 5 "ssr:|fallback:|spa:" nuxt.config.tsRepository: npmx-dev/npmx.dev
Length of output: 3925
🏁 Script executed:
# Check how Nitro handles the render:html hook during fallback serving
rg -B 5 -A 5 "render:html" server/
# Look for event.path usage in other plugins/middleware to understand what value it has
rg "event\.path" server/ -B 2 -A 2Repository: npmx-dev/npmx.dev
Length of output: 1753
🏁 Script executed:
# Check if there's any rewrite/redirect logic that might change event.path
rg -B 3 -A 3 "spa\.prerender-fallback"
# Look for other render:html hooks that might provide insight into how fallback rendering works
rg -B 5 -A 5 "prerender-fallback"Repository: npmx-dev/npmx.dev
Length of output: 2118
Confirm fallback detection matches Nitro's SPA behaviour – the guard condition is ineffective for dynamic routes.
The check event.path.includes('/200.html') will only match direct requests to /200.html. When Nitro serves the SPA fallback for routes like /package/:id (via spa.prerender-fallback.html), event.path retains the original requested path (e.g. /package/lodash), not /200.html. The noscript refresh injection will never run for fallback requests to dynamic routes. Either check for specific fallback routes directly (e.g. event.path.startsWith('/package/')) or use a different mechanism to detect fallback serving.
server/plugins/fallback-ui.ts
Outdated
| if (event.path.includes('/200.html')) { | ||
| html.head.push('<noscript><meta http-equiv="refresh" content="0"></noscript>') |
There was a problem hiding this comment.
Avoid an infinite no‑JS refresh loop.
A meta refresh without a URL reloads the same document; with content="0" this becomes a tight loop for users without JS and effectively blocks interaction. Add a URL target and a one‑time guard to break the cycle.
🛠️ Proposed fix to break the refresh loop
export default defineNitroPlugin(nitroApp => {
nitroApp.hooks.hook('render:html', (html, { event }) => {
- if (event.path.includes('/200.html')) {
- html.head.push('<noscript><meta http-equiv="refresh" content="0"></noscript>')
- }
+ const requestUrl = event.node.req.url ?? event.path
+ const pathOnly = requestUrl.split('?')[0]
+ const isFallback = pathOnly.endsWith('/200.html')
+ const hasNoJsGuard = requestUrl.includes('__nojs=1')
+ if (isFallback && !hasNoJsGuard) {
+ const separator = requestUrl.includes('?') ? '&' : '?'
+ const target = `${requestUrl}${separator}__nojs=1`
+ html.head.push(`<noscript><meta http-equiv="refresh" content="0;url=${target}"></noscript>`)
+ }
})
})
resolves #1291
Description
This pr adds a nitro server plugin that injects a
<meta http-equiv="refresh">tag specifically into the SPA fallback shell (200.html), wrapped in a<noscript>block.