Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

feat(nuxt): payload rendering support #6455

Merged
merged 56 commits into from Sep 10, 2022
Merged

feat(nuxt): payload rendering support #6455

merged 56 commits into from Sep 10, 2022

Conversation

pi0
Copy link
Member

@pi0 pi0 commented Aug 9, 2022

πŸ”— Linked issue

nuxt/nuxt#14507

❓ Type of change

  • πŸ“– Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • πŸ‘Œ 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
  • Adds prefetchPayload(url) composable
    • Server-side: Add link with modulepreload rel
    • Client-side: calls usePayload(url) to fill in the cache Same as server adds modulepreload to trigger browser prefetching in background
  • When using nuxt generate or prefetchPayload(url), it detect rendering mode based on headers and sets the x-nitro-prerender hint to prerender /[route]/_payload.js file
  • Add prerenderedAt to the payload when using prerendering or nuxt generate
  • Add isPrerendered composable (check active payload)

Testing:

Todo:

  • Cache prerender payload to avoid duplicate render
  • Replace payload from prerendered links to an external file
  • Add prerender header for prerendered pages
  • Load payload on navigation
  • Payload filtering for unassigned keys
  • Assign state on navigation
  • Run basic tests

πŸ“ Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@netlify
Copy link

netlify bot commented Aug 9, 2022

βœ… Deploy Preview for nuxt3-docs canceled.

Name Link
πŸ”¨ Latest commit 374429a
πŸ” Latest deploy log https://app.netlify.com/sites/nuxt3-docs/deploys/631c978483f016000846ff76

@pi0 pi0 changed the title feat(nuxt): add payload js endpoint feat(nuxt): payload extraction support Aug 9, 2022
@pi0 pi0 mentioned this pull request Aug 9, 2022
6 tasks
@pi0 pi0 changed the title feat(nuxt): payload extraction support feat(nuxt): payload extraction and prerendering support Aug 9, 2022
@pi0 pi0 requested review from danielroe, antfu and Atinux August 9, 2022 21:20
@pi0 pi0 changed the title feat(nuxt): payload extraction and prerendering support feat(nuxt): payload prerendering support Aug 9, 2022
Copy link
Member

@danielroe danielroe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❀️ This looks great! Would be nice to see some tests as well.

packages/schema/src/config/router.ts Outdated Show resolved Hide resolved
packages/nuxt/src/core/runtime/nitro/renderer.ts Outdated Show resolved Hide resolved
@danielroe danielroe self-requested a review September 7, 2022 12:34
@danielroe
Copy link
Member

Mind if I push a test suite later this evening before merging?

@pi0 pi0 mentioned this pull request Sep 9, 2022
Copy link
Member

@danielroe danielroe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

Some suggestions for follow-up PRs:

  • 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
  • hybrid mode (as you mention)
  • process.env.prerender - presumably we'll set this somehow in nitropack whilst prerendering?
  • 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.
  • [another note: would be nice to have support for testing generated or hybrid sites in test-utils - cc: @antfu]

@pi0
Copy link
Member Author

pi0 commented Sep 10, 2022

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?

test/basic.test.ts Outdated Show resolved Hide resolved
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants