framework
framework copied to clipboard
feat(nuxt): payload prerendering support
🔗 Linked issue
#6411
❓ Type of change
- [ ] 📖 Documentation (updates to the documentation or readme)
- [ ] 🐞 Bug fix (a non-breaking change that fixes an issue)
- [x] 👌 Enhancement (improving an existing functionality like performance)
- [ ] ✨ New feature (a non-breaking change that adds functionality)
- [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change)
📚 Description
This PR:
- Adds new extension to renderer that by adding
/_payload.js
to the end of the URL, returning only payload chunk - Adds
loadPayload(url, force?)
composable- Client-side: Uses browser dynamic import to import and cache payload
- Server-side: No-op and returns null
- Adds
prefetchPayload(url)
composable- Server-side: Add link with
modulepreload
rel - Client-side: ~~calls
usePayload(url)
to fill in the cache~~ Same as server addsmodulepreload
to trigger browser prefetching in background
- Server-side: Add link with
- When using
nuxt generate
orprefetchPayload(url)
, it detect rendering mode based on headers and sets thex-nitro-prerender
hint to prerender/[route]/_payload.js
file - Add
prerenderedAt
to the payload when using prerendering or nuxt generate - Add
isPrerender
composable (check active payload)
Testing:
-
yarn nuxt build test/fixtures/basic
-
node test/fixtures/basic/.output/server/index.mjs
- https://localhost:3000/random/a
Todo:
- [x] Cache prerender payload to avoid duplicate render
- [x] Replace payload from prerendered links to an external file
- [x] Add prerender header for prerendered pages
- [x] Load payload on navigation
- [ ] Assign state on navigation
- [ ] Payload filtering for unassigned keys
- [ ] Run basic tests
📝 Checklist
- [ ] I have linked an issue or discussion.
- [ ] I have updated the documentation accordingly.
Deploy Preview for nuxt3-docs canceled.
Name | Link |
---|---|
Latest commit | 374429af968ba507ff4df0800c4c0ee6f658be89 |
Latest deploy log | https://app.netlify.com/sites/nuxt3-docs/deploys/631c978483f016000846ff76 |
Mind if I push a test suite later this evening before merging?
Thanks for helping to add tests @danielroe ❤️ Regarding your notes:
enabling static in dev mode without the method I used in tests - user may have an API that can't be called from browser or relies on server-only api keys
Later, with route rules, we could predict which routes are prerendered/static to adjust behavior. But note that payload rendering is not only for static mode (ie: server API keys available during prerendering phase. that should work in production too and with API fallback)
process.env.prerender - presumably we'll set this somehow in nitropack whilst prerendering?
It is already added and released from nitropack which I've used. If it doesn't work, not only is a performance issue but a security issue because an attacker could fill the memory of server by abusing payload cache. I plan to improve it later with a shared LRU.
would be nice to deduplicate payloads - e.g. if you hard load /random/a then it should 'fill' the payload and not redownload it when navigating from a -> b -> a.
Not quite sure to understand this. Payload state is fresh per page and payload URL is unique. We don't download by with but use dynamic import. Browsers have caching mechanism for esm imports and don't redownload. (unless using new hash to force download a new payload). Also note that we are splitting data/state from initial payload (runtime config and other top level keys)
would be nice to have support for testing generated or hybrid sites in test-utils
Do you mind to open an issue to elaborate more about your idea about possible utils?