Check out a free preview of the full Fullstack Svelte with SvelteKit course

The "Page Options" Lesson is part of the full, Fullstack Svelte with SvelteKit course featured in this preview video. Here's what you'd learn in this lesson:

Rich discusses exporting page options from the page, page.server, layout, and layout.server modules. Examples of the ssr, csr, prerender, and trailingSlash page options are demonstrated in this segment.


Transcript from the "Page Options" Lesson

>> So in the chapter on loading data, we saw how you can export a load function from your page server JS and your layout server JS files, but we can also export page options from those files. We can export an SSR boolean, a CSR boolean, a prerender value and a trailingSlash value.

And these control how the page behaves. And in the following exercise, we are gonna learn about each of these, in turn. All of the page options that we're about to discuss, can be exported from individual pages, or they can be applied to groups of pages by exporting them from a layout file.

So if you want some behavior to apply to your entire application, you can put it in a root +layout.js file. And then in child pages, you can enable or disable other aspects of that behavior as you need. This allows you to mix and match different behaviors in your application.

For example, you can have an application that is mostly prerendered as static HTML, but has some dynamic pages that are rendered with personalized data for example. And so this makes SvelteKit very versatile for whatever kind of application you're building. The first one we're gonna learn about is SSR.

So Server-Side Rendering is the process of generating HTML on the server, and it's what SvelteKit does by default. It's very important for performance and resilience, it's very beneficial for search engine optimization, right? While some search engines cannot index content that is rendered in the browser with JavaScript, it happens less frequently and it happens less reliably.

So SSR is a really important default to have. Having said that, there are some components that cannot be rendered on the server. Maybe they expect to be able to access browser globals like 'window' immediately. And ideally you would change those components so that they can be used on the server, but sometimes that's just not possible.

So in some situations you might need to disable server-side rendering. We can do that in a page.server.js, With export const ssr = false. Right, and this will allow this page here to be rendered without breaking the app, because if we were to server render this without ssr = false, if you had the default ssr = true.

Then we get an internal error when we try and server render this page, because window is not available on the server. This is a component that cannot be rendered in a server environment. The counterpart to SSR is CSR. Client-Side Rendering is what makes the page interactive. So here we have a button, when we click on it, it's gonna increment the count, right?

It also enables SvelteKit to update the page upon navigation without causing a full page reload. And you can disable it using a page option add a page.server.js file. I'm gonna export const CSR equals false, right? This means that no JavaScript is getting sent to the client at all.

But also it means that our components are no longer interactive, if I click on this button nothing is going to happen. So most of the time you're not going to use this option, you're not going to use this option but it is a useful way to be able to find out how your app is gonna behave for users who, for whatever reason, cannot use JavaScript.

Okay, let's talk about prerendering. Prerendering means generating HTML for a page once at build time. Rather than dynamically for every request that comes into your server. The advantage of prerendering is that serving static data is extremely cheap and performant. So it means that you can serve a very large number of users without worrying about things like cash control headers, which are very easy to get wrong.

But the tradeoff is that the build process will take longer, and so prerendered content can only be updated by building and deploying a new version of the application. So it's up to you when it's appropriate to use this. If you wanna prerender a page then you just export const prerender = true, again, from your page server js.

All right this isn't gonna have any observable effects here in the tutorial because we're we're running the application in dev mode and nothing gets prerendered during development, this is a thing that happens when you run npm run build. Not everything can be prerendered, right? If you're building something that uses dynamic data, then you can't have an HTML file for that.

Basic rule of thumb is that if any two users hitting that URL are gonna get the exact same content in all circumstances. Then that page is a good candidate for prerendering. You can prerender pages with dynamic parameters like earlier when we had /blog/slug and square brackets. We can prerender things like that as long as SvelteKit can find them, either by you having specified that in your SvelteConfig or by SvelteKit being able to find a link to those pages from crawling your application.

So if you set prerender to true inside your root layout server.js, then you've effectively turned SvelteKit into a static site generator. This is what you would do, for example, if you're using adapter static, which is the adapter that allows SvelteKit to build applications that can be hosted on places like GitHub pages.

The final page option that we're gonna look at is trailingSlash. So two URLs like /foo and /foo/, they might look the same, but they are actually very different. A relative URL like ./bar will resolve to /bar in the first case, but /foo/bar in the second. And search engines will treat those two URLs as distinct, which harms your SEO.

So you don't wanna be loose about your trailingSlash. You wanna pick one and stick to it. And the default behavior that SvelteKit chooses is to remove trailing slashes. So that if you do have a request for /foo/, SvelteKit will turn that into a request for /foo. So we can see that here, we have a bunch of URLs in the nav bar, and if I click on always/, it's just gonna go to /always.

And these haven't been implemented yet, so they're all gonna behave the same way. If we go to the always/page.server.js, And add export const trailingSlash = always, then now the behavior is gonna be reversed. If I navigate to /always/, that's the URL that I get. If I navigate to /always without the slash, It will end up on the same place.

If we wanna accommodate both cases, which is not recommended, then you can add the ignore value Right, and now if I navigate to /ignore without the trailingSlash, that's what I'll get, ditto if I add the trailingSlash. There are very few situations where this is appropriate, most of the time you will be using either, always, or never.

And this also affects prerendering. If you have a trailingSlash, then it'll be prerendered as an index.html file inside a directory. If the trailingSlash is removed, then a URL like /never will become never.html. And that's something that you might need to configure with your static web server if that's how you're deploying your application.

>> Have you seen people make installable PWA with Svelte and do you feel like that? Or have you seen traction with PWAs, whether it's worth it or versus building something for the app store or whatever?
>> It's certainly possible to build a progressive web app with SvelteKit.

It gives you all the tools that you need to add a service worker and you can add a manifest.json in your static folder. It also works with a library called Vite Plugin PWA, which does a lot of the grunt work for you. So absolutely, it's something that you can do.

I couldn't tell you how widespread that is, how many people are building things in that style, but it's completely achievable.
>> If I understand correctly, using prerender true and layout.server.js is the same as using an adapter static.
>> You need to do both, essentially, if you use adapter static and you're not prerendering, then it's gonna yell at you because it's gonna say, hang on a minute, we have some non-prerendered routes here, and it'll tell you how to resolve that.

So if you are using adapter static, then you probably want to have export cons prerendered true from your root +layout.server.js. But there are some situations in which you might have the bulk of your site pre-endered, but then have a few things that only use client-side rendering, for example.

And so it's not a hard requirement that every page in your app is prerendered if you are using adapter static. You can use it to build a fully client rendered single page app for example.
>> I had a situation where the only way to find a link to get to some set of blog posts and a prerendered TEDx it was to click through a client side post paginator that had collapsed page buttons that Svelte didn't like through all of the page links.

Is there a way to get some kind of file manifest for all routes that SvelteKit finds? So I don't have to made any update entries data in my SvelteKit config.
>> Yeah, hold that thought, so there is a pull request open on the SvelteKit repo right now by Elliott Johnson, one of our core team members that adds a new export from your page server js files called entries.

This is a function that you define per route when you have dynamic parameters. It returns an array of all of the valid paths for that page. So if you have something like /blog/slug, then you can define an entries function on that file that will communicate with your CMS, grab whatever data it needs to, and then tell the prerenderer these are the pages that need to be pre-rendered.

Right now you have to do that in your Svelte config, but very soon you'll be able to do it in the page itself.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now