I am porting my Next.js site to Sapper for performance reasons, but my Sapper is performing very bad. Long load times (around 15 seconds for a page, if not served from cache). My API is very fast, so it can't be the issue.
I use Vercel hosting. But both there, and on my machine, the render times are about 15 seconds.
Since I'm new to Sapper, I suspect I might be doing something the wrong way.
One thing I don't feel comfortable with, is that I pass global site settings (menu structure etc) from server.js in the function named "session". However this isn't something like a session object that contains user-specific data. It was the only way I found to achieve a global store in Sapper (accessible by both _layout.svelte and route pages) - if this is dirty, I hope someone can tell me another way.
And the other thing that concerns me is that I subscribe to the session in many different components - in order for them to have access to the global store.
Below is my current setup, summarized.
I fetch the site globals inside server.js, and pass them into the session. This was the only way I could find to enable me to access a global store from both _layout.svelte and my routes ([...slug]).svelte. I also add the stale-while-revalidate header, for Vercel's caching
const server = polka()
.use(
compression({ threshold: 0 }),
(req, res, next) => {
res.setHeader(
"Cache-Control",
"s-maxage=1, stale-while-revalidate"
);
next();
},
sirv("static", { dev }),
sapper.middleware({
session: async ({ headers }) => {
const request = await fetch(
`https://MY_BACKEND/globals`
);
const { app } = await request.json();
return {
app,
origin: `https://${headers.host}`
};
}
})
);
_layout.svelte
<script>
import { stores } from "@sapper/app";
const { session } = stores();
let mainMenu = [];
session.subscribe(({app}) => {
mainMenu = app.mainMenu;
});
</script>
[...slug].svelte
<script context="module">
export async function preload({ params },{ app }) {
const page = await this.fetch(`${params.slug.join('/')}.json`).then(r=>r.json());
...some processing which uses the 'app' globals, and the page...
return {...}
}
</script>
Inside components that need access to the global store (these can be many)
<script>
import { stores } from "@sapper/app";
let something = '';
const { session } = stores();
session.subscribe(({app}) => {
something = app.something
});
</script>