I love static websites, because they are very fast and very good for SEO, google can 'read' it much better. But these days you need JavaScript almost everywhere.
And I like Svelte as very easy to learn and use lightweight framework.
I've found out, that it's not very simple to mix static rendering and CSR on same page. But possible. I will use time (JavaScript Date() result) as example data, but in production it can be your data, e.g. "BFGoodrich tyre" or "Red apples" or "War and Peace by Leo Tolstoy".
Our example page will print very simple text:
Date: Wed, 18 Jan 2023 15:49:03 GMT
Build: Wed, 18 Jan 2023 15:49:01 GMT
First line (Date:) is content you calculated on client-side, when page is loaded. Second line (Build:) is build-time, something you calculated during npm run build
which must be visible to search engine.
Create project
npm create svelte@latest hybrid
cd hybrid
npm install
Enable static adapter
Install it: npm i -D @sveltejs/adapter-static
In svelte.config.js disable adapter-auto and use adapter-static:
import adapter from '@sveltejs/adapter-static';
Now you can generate static website with npm run build
and preview it with npm run preview
.
src/routes/+page.server.js
export const prerender = true
export function load() {
return {
t: new Date().toUTCString()
}
}
src/routes/+page.svelte:
<script>
import { browser } from '$app/environment';
export let data;
var buildtime = data.t
</script>
Date: {#if browser}{new Date().toUTCString()}{/if}
<br>
Build: {buildtime}
Result
run: npm run build && npm run preview
and open http://localhost:4173/ you will see result. If you will reload page in a second, Date will change, but Build will stay same.
Also, if you will open build/index.html you will see there:
...
Date:
<br>
Build: Wed, 18 Jan 2023 15:58:18 GMT
...
As you see, our statically generated content is clearly visible in page.
Explanation
in +page.server.js
we set prerendering=true
to generate static HTML site (with JS) as a result. And we return data with current Date(). We must convert it to string here, because client browser may have different timezone and Build: date will be "flashing" (initially it will have date in our timezone, and in fraction of second it will be overwritten). Not nice.
in +page.svelte
we use this data. Also we conditionally display new Date() (I used .toUTCString()
here just to have both dates to look similar, it's not really needed).
Without {#if}
you'd get one date built-in HTML (displayed immediately when page loaded) and other date will overwrite it. Not nice visual effect. With {#if}
we suppress first date and display only CSR date over empty page space.
Using this method you can combine benefits for static and client-side rendered content at any SvelteKit page.
Top comments (0)