Search code examples
javascriptsveltesveltekitprerender

How can I use adapter-static in SvelteKit to prerender my site without calling LayoutLoad in parallel?


I have a SvelteKit site that uses adapter-static to prerender pages. It's a multilingual site, so I pass the paths /, /de, /es, pt in svelte.config.js. For translation I use sveltekit-i18n.

I have

  • routes/+page.svelte,
  • routes/de/+page.svelte,
  • routes/es/+page.svelte
  • routes/pt/+page.svelte

The problem is sveltekit-i18n and most i18n libraries use a reactive variable $t and when the pages are built, it runs the LayoutLoad functions in parallel for these sites. In my LayoutLoad (routes/layout.ts) and LayoutServerLoad (routes/+layout.server.ts)` I have something like this:

/** @type {import('./$types').LayoutServerLoad} */
export async function load(attrs: any) {
    const startsWith = ['pt', 'es', 'de'].find((e) => attrs?.url?.pathname.startsWith(`/${e}`));

    const locale = startsWith ?? defaultLocale;
    await loadTranslations(initLocale, attrs?.url?.pathname);
    return { locale };
}

and this

/** @type {import('./$types').LayoutLoad} */
export async function load({ data, url, parent }: any) {
    await loadTranslations(data.locale, url?.pathname);
    return { locale: data.locale };
}

now when I build my site with SvelteKit via vite build then I find out that the load functions are loaded like this by using console.log

layout.server.ts es /es
layout.server.ts pt /pt
layout.server.ts de /de
layout.ts es /es
layout.ts pt /pt
layout.svelte es /es
page.svelte pt /es
layout.ts de /de
layout.svelte de /de
page.svelte de /de
layout.svelte pt /pt
page.svelte de /pt
layout.server.ts en /
layout.ts en /
layout.svelte en /
page.svelte en /

as you can see the page /es/+page.svelte has suddenly the language pt and not es.
The same applies to the page /pt/+page.svelte it suddenly has the language German de.
I believe this is due to the reactivity of the $t variable in i18n libraries like sveltekit-i18n, but I also don't know how to fix it, as load functions seem to be loaded in parallel and not right before the +page.svelte is being built. So what happens I have in my prerendered output html files the wrong language, for example in meta description tags etc.
I appreciate your help very much!


Solution

  • When I replicated the issue using a skeleton SvelteKit project, I noticed that I had set the concurrency level to 3 in prerender options in svelte.config.js. This causes the mixed order of load runs above, setting it to 1 solved the problem.

    /** @type {import('@sveltejs/kit').Config} */
    const config = {
        preprocess: preprocess({
            sass: true,
            postcss: true
        }),
        kit: {
            adapter: adapter(),
            prerender: {
                concurrency: 1, // had to be set to 1 instead of 3
                crawl: true,
                entries: pages
            }
        }
    };