-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Static rendering all the routes, even the parameterized ones #1533
Comments
It's not clear to me what you're requesting. Do you have a concise way of stating it? Parameterized routes are currently prerendered, but must be either linked to or specified as an option |
Yes, parameterized routes are pre-rendered but that works best for a set of known values. Pre-rendering routes that have wildcard values where the values aren't known until request time isn't that well supported at the moment. It can be done (that's what my linked demo shows) but requires some fairly ugly parsing of the HTML artifacts. I think there might ultimately be 3 feature requests to make it smoother:
It may be the case that what I'm trying to do is so uncommon that it doesn't belong in SvelteKit but in some other framework built on Svelte. Wanted to see if there's any interest. |
Also this runtime server-side interpolation into the HTML file, that is only one way to approach it. It could just include a copy of the route parsing logic in there. Then you could still serve your HTML files off a CDN and enjoy routes with placeholders. So in your
You might have essentially a slice of the manifest that relates to that particular route, i.e. the regex with capture groups, and list of positional route param names. So like:
I need to make a branch on my demo repository and explore this. The advantage of this is it could be done as a post build step, or even just part of the regular build if it was integrated into SvelteKit, instead of needing per-request interpolation. I don't want to add to your open bug count, you can resolve this if you want, people can still find it in the history. |
This seems over-complicated. You just need to create a directory page which generates a link for each parameter value |
The values are infinite though. |
Or I should say arbitrarily large, and constantly changing. |
Basically I've got this pretty sweet prototype I'm building, it's way way faster than our extra-large Angular app even though it's doing full page reloads on every transition. I'm currently just serving it with |
I'm on discord as "jpsimons" just FYI. |
You can't prerender an infinite number of pages because the pretenders process would never end. You can prerender arbitrary / changing pages though by generating the links in the directory page accordingly |
I'm trying to pre-render one page, but one page that's parameterized, where the parameter is filled in at runtime from the path. |
If you can provide a list of all possible values of the parameter from a database or some other source you can prerender that page. If there are an infinite / arbitrarily large number of possible values and you cannot provide a list then you can't prerender now and never will be able to with any software because that's impossible. |
Sorry I think I'm explaining more but not explaining better... these are pages that have no |
Ok. So just prerender that page then. I don't understand what the problem is. This whole thread is indecipherable to me. You might try asking for help on Discord instead |
Ohhh, I think I finally figured out what you're trying to say. You want to prerender a page where the route parameter is not used in |
Exactly, my write-up was too wordy! Pre-rendering with [TODO] deferred values, deferred until runtime. |
So I made up a scheme for it, and wanted to share, but it could be more streamlined and more integrated into SvelteKit if we wanted. The one thing that makes me nervous is the svelte file path in the manifest.js is just in comments, I need those and hope they don't go away. |
This thread is really long and confusing. I'm going to close it and file a new issue referencing this one with a clearer description |
Hey guys, I came across a similar problem. For me routing on Here is the setup (sliced) filestructure .
├── __error.svelte
├── index.svelte
├── __layout.svelte
├── shop
│ ├── [accessory].svelte
│ └── index.svelte
├── [...slug].svelte As you can see, I am using a wildcard route
When creating the routes manually (slug1, slug2...), they get properly generated in build folder and routing works on Here you can check the behavior
Is there a way to work around this, somehow specifying the routes somewhere? My two cents on the topic Did you think about crawling the site for links you could possibly prerender? Like
To be fair with you, build time will drastically increase. However that's not a big deal for me personally. |
What does your kit.prerender.pages look like? If your slugs are constantly changing, keep mind that you can still pre-render of course but any parts of the page that are data-fed by request specific information will have to be client-rendered. If the page in its entirety is data-fed by request specific params, probably no point in static pre-rendering at all. I'm a little unclear on your ultimate hosting solution. If it's Vercel, why not use adapter-vercel instead of adapter-static? adapter-static would be for a simple static file server, or as I'm pushing forward, a completely custom server runtime (the latter of which could allow query strings, path params, rest params, etc). |
Hi, thanks for your reply. svelte.config.js prerender: {
crawl: true,
enabled: true,
force: false,
pages: [
"*",
"/ari-personenfahrzeuge",
"/elektrotransporter-ari-901/kofferaufbau",
// other routes generated in [...slug]
],
} To answer you questions: Just out of curiosity, the config states Nonetheless the config works absolutely fine. I'd love a function in future, which crawls links from pages and prerenders them. |
I think I understand... new pages come into existence constantly, but you only them to be published on the next build/deploy? And you don't want to have to list them all out in the |
I'd try this just to test: Add a parameterized route without rest params, such as |
Maybe crawling stops at routes with params in them, by design, to avoid pre-rendering your entire database. Maybe you also aready mentioned such in your description, I should read more carefully. Sounds like we might want a new option for |
Yes, that's right. The bug I found was in regards to routing, when loading the page first. I assume you differentiate routing on first page load and when clicking a relative link on the site. So refreshing the page in the browser did load the wrong page content, even when the url stayed correct.
Edit:
In my case, I really want to prerender to entire database :D, or lets say all the pages/posts. |
To be honest, I expected If someone doesn't want to pre-render the entire database, one should set the pages to be rendered in the These are my two cents from reading the documentation, as I can't find this problem mentioned anywhere in the docs. |
This! In my case I'm trying to set up a simple blog that renders pages based on markdown files. |
So I was actually thinking more about rendering a generic version of a dynamic route, and actually this literally just came up again at my current employer... I want to use adapter static to spit out some html files and an _app folder that I can drop in an existing web server setup (in my case it's Java/Dropwizard/Maven). You can actually pull this off just fine by adding a prototypical example for each parameterized route in pages, i.e.
Then do a little URL rewriting in your web server, something like:
The downside here is the realtime path params won't come through in the page store params, but you can simply inspect location.pathname yourself. However... if you navigate from say |
so this is still a thing to be done? i am new to svelte/svelteKit, did a little research on other frameworks (gatsbyjs for example) and seek for the ability to create static pages from dynamic routes. i too thought the crawl option would unfold all those dynamic routes [page].svelte to static html pages based on the result of an api result. is there any solution to that? any help is appreciated |
You need to either link to each page somewhere within your app so that it will be crawled or you need to list each page in the |
i have an api route to fetch users (using faker.js - older version; not 6.6.6) the result of that list is used by module load() in my index.svelte route and links each entry as a detail page using a dynamic route [user].svelte the second api [user].js fakes additional data for that user. npm run dev works perfectly fine, prefetching does its thing and data is shown on the list and user page. all fine. but npm run build only renders my list page. you mentioned to add prerender.entries
maybe i have a missconception of what adapter static and prerender does... |
You would need to file an issue and provide a code repository that reproduces the issue. I'm not sure why crawling wouldn't work for you |
Was my next thought, to provide some reproducible code
I will do that and link it here
Thank you
… On 01.02.2022, at 14:19, Ben McCann ***@***.***> wrote:
You would need to file an issue and provide a code repository that reproduces the issue. I'm not sure why crawling wouldn't work for you
—
Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you commented.
|
Why is this closed? Now it is impossible to create a static page with dynamic params. I think it is not uncommon that you don't know your data on build time. |
If I get it correctly and the problem is the same as mine: You have a route After very much research, I came to the solution to
That way the path is properly build and can be visited properly in both What else I tried and failed or didn't work for me:
|
I'm not quite sure I understand... I think your first bullet point is on the right track... although in my case at my current employer, our build/deploy system chokes on square brackets, maybe having something to do with bash escaping, so I used underscores instead. As far as going directly to |
@johnnysprinkles If you have a completely static site and no power over the server then you would just get a 404 on I created a PR that should work on your example: https://github.com/johnnysprinkles/static-all-the-things/pull/1 But anyway, I think that using the |
Oh I see, your web server is just a simple CDN so yeah, path params aren't an option. But your CDN will probably wildcard route all query-string suffixed URLs to the same filename. In that case, why use load() at all? Why not simply examine |
Oh maybe I see what you're saying, |
You cannot access searchParams onMount, it throws an error on prerender. You can though ( I found out later ) condition if the code is running on the browser or on prerender: https://kit.svelte.dev/docs/modules#$app-env and do the same thing I did with the try/catch but with an
And then render a placeholder page if there are no params. And as you already said, the pages are indeed in a CDN so it should be just dump static html pages. |
I have read through all of the answers. Is there any update on this one? I have a folder structure like this: ─ src The thing is I have 0 references to blog_post page in blog page because in the blog page I get active blog posts from an API. I create links through slugs of the blogposts. Like "example.com/blog/blog-about-something". The problem I am having is when I run static generation it has 0 references to blog posts page because blogs page is generated dynamically on client side as well. I want to generate my navbar, footer and other elements statically and use my custom js fetch function to fill the blog post data. When I run the build it says crawling was unable to find references to blog_post page. If I add a reference like Sorry if this diverges from the main post of this thread but I think we have same problem. |
This is my exploration into the idea of static rendering all the routes such that they can be served in a totally language agnostic way. This is of course easy to do already for routes with no route params, but not so simple for the parameterized routes.
Why would I want to pre-render a parameterized route, where all the data comes from the clientside XHR call? Aren't I just prerendering a blank page? Not at all my friend, you prerender as much as you can which would typically include at least the global nav bar. Having that appear instantly instead of merely quickly upon hydration makes all the difference in giving your site an app-like feel.
And in my case it's especially important since I'm not using client-side routing, so each page load needs to be as fast-feeling as possible. Why no client-side routing? Imagine a large site with 1000 pages, an in-house project spanning many years and having many separate teams. Building this as a single app is bound to result in slow build times, so you can split it up into 10 Svelte projects where each has 100 pages (all behind a reverse proxy). But as long as you're splitting it at all it makes sense to just split it completely with full page reloads on every transition. Now you can reproportion ownership fluidly as you see fit, and most importantly, you can iteratively migrate page by page to some new framework. Perhaps whatever the hot framework of 2025 is. This a whole separate topic I could say a lot about but let's leave it at that.
So anyway, the
'*'
you pass tokit.prerender.pages
only does the parameterless routes. A first attempt at this might be to add another route in there that has garbage for the param since it won't even be looked at from the serverside, and updating your code that runsonMount
to only look atwindow.location
instead of the page store.I put together a repo to try out some ideas, at https://github.com/johnnysprinkles/static-all-the-things
Setup
The first commit is just setting things up with a small constellation of services to make a more realistic prod-like setup. There's SvelteKit, there's a simple API server, and there's a web server that serves the adapter-static compiled assets off of disk. Just to ensure we have a complete break between build time and runtime the web server is written in Python. Could be anything (for me it'll probably be Java or Kotlin), but all the matters is it's not Node.
On the SvelteKit side I added two routes related to airplanes, one is a parameterless List page, and one is a detail page that has an
[id]
in its route.https://github.com/johnnysprinkles/static-all-the-things/commit/b06f612a31b4009e5a44a4b05b97f7c7cffd37f1
This example just gives you a 404 for the parameterized routes.
First pass
https://github.com/johnnysprinkles/static-all-the-things/commit/3be17a2a84147cdc516f83c756fd72ebe021ce65
This manually adds preprender paths with garbage for the parameters, and it does work. I can run it and my dynamic pages function. It's all hacked up and manual though, we can do better.
First attempt at interpolating
We'd really like to keep using the store, which should be a source of truth for route params and other request-specific data, instead of going around it to inspect the
window.location
. So instead of passing garbage for the params when server-side rendering, what about if we pass something meaningful? Such as just the param name in square brackets? (I know, this is kind of overloading the meaning of square brackets, but it's just a start).If we do that, we can just have the web server replace e.g.
[id]
with the actual ID. A hacked up and manual version of this is in:https://github.com/johnnysprinkles/static-all-the-things/commit/5ed2e708ec1a355788b8bfb9deb24ff70d51b8e2
More automated way of interpolating
We can tidy things up a bit by taking advantage of the manifest.js file, which knows both the names of all the route params (in JS comments) and the regexes that match, e.g.
So the next version of this reads and parses that:
https://github.com/johnnysprinkles/static-all-the-things/commit/22e3e98149876364d8a4317e9557f727e2287021
It would be nice if we had routes presented in a language agnostic way, such as a
routes.json
file that lives next to the manifest. A possible feature request.Once we have that we can fill in the page store via regex slice and dice. This would be a little easier if the page store data was pulled out of that structure (and also perhaps surrounded by special comment tokens). So for example we currently get this:
But if it were more like this it would be easier for any language that can emit JSON to fill it in:
So that's where things are at now, this will be an ongoing exploration.
The text was updated successfully, but these errors were encountered: