kit: prerender = true in /+layout.server.ts breaks the route after deployment to netlify / vercel
Describe the bug
I found this bug in one of my bigger projects after migrating to the new routing configuration. It took me a while to pinpoint that it was the prerender = true
setting in /+layout.server.ts
that was causing the bug. The project runs fine locally using pnpm dev || pnpm build || pnpm preview. The project also has no problem building once deployed to Netlify / Vercel. It’s only after publishing that it breaks.
I created a new project from scratch and was able to recreate the bug when deployed to both netlify and vercel.
-
The repo for the scratch project is here: https://github.com/StephenGunn/layoutprerender
-
The deployment on Netlify is here: https://glittering-mermaid-5b82d2.netlify.app
-
The deployment on Vercel is here: https://layoutprerender.vercel.app
You’ll be able to see the 500 error on both Netlify and Vercel using the above links. I also have examples of the exact same code but with prerendering not set and the routes work as intended.
I tried to make the code and example as clear as possible, let me know if you have any questions.
EDIT: prerender = true works on normal /+page.server.ts powered routes from my testing
Reproduction
- clone https://github.com/StephenGunn/layoutprerender and deploy to netlify or vercel
Logs
Netlify doesn't seem to log any error in the render.js function logs.
Vercel logs this: [GET] /episodes-3/__data.js?__invalid=nyn&__id=1
The error on the frontend is this:
500
Failed to fetch dynamically imported module: https://layoutprerender.vercel.app/episodes-3/__data.js?__invalid=nyn&__id=1
TypeError: Failed to fetch dynamically imported module: https://layoutprerender.vercel.app/episodes-3/__data.js?__invalid=nyn&__id=1
System Info
Netlify / Vercel
Severity
annoyance
Additional Information
Marked as an annoyance because I can just turn off prerendering for my /+layout.server.ts and the site works.
But I would like to be able to turn this feature back on since it does slow down certain routes and puts added stress on my backend.
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 5
- Comments: 31 (15 by maintainers)
Commits related to this issue
- throw an error if prerenderable routes are not prerendered (#6568) — committed to sveltejs/kit by Rich-Harris 2 years ago
- [fix] throw an error if prerenderable routes are not prerendered (#6974) Part of #6568 (but not all — still need to regenerate the manifest so that prerender = true routes cannot be dynamically serve... — committed to sveltejs/kit by Rich-Harris 2 years ago
- remove nodes for prerendered routes from manifest - closes #6568 — committed to sveltejs/kit by Rich-Harris 2 years ago
- [feat] remove nodes for prerendered routes from manifest (#7541) closes #6568 — committed to tanhauhau/kit by Rich-Harris 2 years ago
The issue here is that
src/routes/episodes-[number]
is marked as prerenderable by virtue of theexport const prerender = true
insrc/routes/episodes-[number]/+layout.server.ts
, which means the code to generate the__data.js
files needed by the page isn’t included in the deployment to Vercel/Netlify, on the assumption that the__data.js
files were already prerendered. But they weren’t, because the crawler didn’t get to them, because/
(which contains the links the crawler would otherwise follow) is not marked as prerenderable.At the very least, we should make this bug more discoverable by omitting those routes from the manifest used during
preview
, so that it fails locally the same way it fails in production.One solution could be to always render pages, whether or not they’re marked as prerenderable, so that the crawler can find prerenderable pages via non-prerenderable pages. Non-prerenderable pages would just be discarded. But this would make everyone’s builds much slower. Another (probably much more sensible) possibility would be to print a warning or error if a route was marked as prerenderable but wasn’t actually prerendered.
@s3812497 If I comment that line out I get
Oh wait I did have an @migration that I incorrectly fixed. I just had a
export const countries = [...]
in js file I was importing and moved it some +server.js file I think. I put in data.js file and imported in +page.svelte file and works. My badThe title is misleading as the actual issue is SvelteKit does not pre-render dynamic routes marked for prerender, leading to missing html files. This only occurs when there aren’t any non-dynamic routes also marked for prerender.
Creating my own store was very simple, just had to wrap my thick head around the need to. Thanks again for your help.
If anyone is reading this wondering if we solved the original issue, we did not. @s3812497 just helped me figure out a few things.
Yes, the layout server load function is not re-run. The data stays the same as it was during build.
Yeah, you’ll just want to mimic the same order of events:
getSession()
on the server and return data to the client)store
(hence, the $session` store).EDIT: Sorry for cluttering the issue. The initial bug is that
build
does not prerender dynamic parameter routes unless a static route is also set for prerendering. See this repository for the reproduction.Just as a follow up- my site was acting weird before I realized that putting prerender = true in the +layout.server.ts prevented my UI from having logged in / logged out state. So I reverted again and I will wait until the original problem is fixed.
Ok, I think adding prerender = true to the root +layout.server.ts and then specifying prerender = false on the routes I want to keep dynamic worked. I’ll keep playing with it and make sure this works for me.
Thank you for helping me!
The original bug still exists though so I’m going to leave this open.
It’s weird that it can’t find the route. What’s the structure of your routes?
In the docs, it mentions the
'*'
value forentries
doesn’t include dynamic routes (must be why it ignores your routes).I’d recommend adding a
prerender = true
to your home page layout instead.So,
has been removed, according to the error I got during build, but is still in the docs.
and any route that I tried to specify with
entries
that had a parameter in the route, failed:I think I was closer before but it was worth the shot.
I’ve never used the option before either, but I would assume the
entries
option would be in addition to per-route configuration.Sounds like the right way to go 😃
The project breaks without it. See https://github.com/sveltejs/kit/issues/6462