-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for prerendering #11539
Add support for prerendering #11539
Conversation
🦋 Changeset detectedLatest commit: fd6493a The changes in this PR will be included in the next version bump. This PR includes changesets to release 7 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
setHeaders: function (res, path, stat) { | ||
if (path.endsWith(".data")) { | ||
res.set("Content-Type", "text/x-turbo"); | ||
} else { | ||
// Cache as an immutable asset for 1 year | ||
// Do this here instead of via the immutable/maxAge headers so we can | ||
// conditionally apply it to assets (which are hashed), and not | ||
// pre-rendered .data files (not hashed) | ||
res.set("Cache-Control", "public, max-age=31536000, immutable"); | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It feels potentially very bad to every put a 1 year immutable cache on a non-hashed .data
URL, so this makes remix-serve
by default not cache data files, and only apply the caching to other assets files.
page, | ||
app, | ||
"#child-error", | ||
"Unable to decode turbo-stream response" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See below, but we can't surface this underlying CDN error any longer with pre-rendering :/
// Can't clone after consuming the body via turbo-stream so we can't | ||
// include the body here. In an ideal world we'd look for a turbo-stream | ||
// content type here, or even X-Remix-Response but then folks can't | ||
// statically deploy their prerendered .data files to a CDN unless they can | ||
// tell that CDN to add special headers to those certain files - which is a | ||
// bit restrictive. | ||
throw new Error("Unable to decode turbo-stream response"); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is why we can't surface the res.text()
of CDN errors
export const isSpaMode = ${ | ||
!ctx.reactRouterConfig.ssr && ctx.reactRouterConfig.prerender == null | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"SPA Mode" is specifically no SSR and only generating a root index.html
- this isSpaMode
flag is what tells the server.client not to SSR/hydrate beyond the root route.
let { handler } = await getPrerenderBuildAndHandler( | ||
viteConfig, | ||
reactRouterConfig, | ||
serverBuildDirectory | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SPA Mode is effectively untouched, just sharing some code for creating the handler with the prerender code paths
packages/remix-dev/vite/plugin.ts
Outdated
if (hasLoaders) { | ||
await prerenderData( | ||
handler, | ||
reactRouterConfig.basename, | ||
path, | ||
clientBuildDirectory, | ||
viteConfig, | ||
requestInit | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prerender .data
files for any routes with at least one loader
Hoping to implement this without runtime change (i.e. without ssg specific if-else branch). ~For now, it uses `(path)/index.data` as an output, so it'll probably require cdn to do rewrite from `(path)?__rsc` to `(path)/index.data`.~ (EDIT: stream request convention is changed to `(path)/__f.data`, so that prerender deployment is easier #361) - [x] react-router style api remix-run/react-router#11539 - [x] full ssg - [x] dynamic route - [ ] static deploy - [x] vite preview - [x] vercel - [ ] cloudflare - [x] test ## future - [ ] customize generation - [ ] `generateStaticParams` https://nextjs.org/docs/app/api-reference/functions/generate-static-params - [ ] auto crawling of `<a>`? - [ ] export `prerender` utility so that users can full control? - [ ] output not-found - [ ] preload flight stream - [ ] tweak browser entry - [ ] ~automatically rewrite `(path)?__rsc` on browser~ - requires #359 - [ ] reduce unnecessary route node re-rendering - requires #353 - [ ] hybrid ssg and ssr - need manifest to rewrite to cdn? - [ ] partial prerendering
Add support for a
prerender
config that pre-renders HMTL and.data
files for whatever URLs you specify. You can then deploy these files to a CDN, and load serve the HTML documents which hydrate into SPA's and load the.data
files on client side navigations