kit
kit copied to clipboard
Base hrefs are not supported in prerendering
Describe the bug
It appears that base hrefs (e.g. <base href="/en/">
) are not supported at the moment. I stumbled against two issues.
One issue is that the prerenderer/crawler grabs all hrefs and resolves the relative references against the current path. The result is something like this:
-
subsection
resolved from/en/section
=>/section/subsection
-
section
resolved from/en/section/subsection
=>/section/section
Note that this works fine in the browser, the problem is only with the prerenderer. I tinkered around with the code and managed to fix it by resolving against base
in this line and the base
itself is fairly easy to obtain in the crawl()
that's called above.
The second issue is that the asset paths are relative. And the base href screws up all of them as ./_app
gets resolved to /en/_app
in the browser. This could be solved by allowing to turn off the asset relativity. It might be as simple as allowing /
in config.kit.paths.assets
. Currently it is refused by a param check with the Error: config.kit.paths.assets option must be an absolute path, if specified.
and Error: config.kit.paths.assets option must not end with '/'.
checks.
Reproduction
https://github.com/tontonsb/sveltekit-base-prerendering
Try npm run dev
and visit http://localhost:5173/en
to observe that you can either follow links or directly visit /en
, /en/section
and /en/section/subsection
.
To observe the problem with the crawler:
- Execute
npm run build
and you'll seeNot found: /section/subsection
- OK, let's make the language prefix optional. Try
git checkout lang-optional
andnpm run build
. Now/section/subsection
will work (as the[[lang=lang]]
prefix is optional in this branch), but you'll stumble againstNot found: /section/section
when it tries to resolvesection
from/section/subsection
. - In case you want more fun, setting
config.kit.prerender.handleHttpError = 'warn'
will throw you into infinite404 /section/section/section/sect...
:)
To observe the problem with assets:
- Do
git checkout assets
andnpm run build && npm run preview
. - Browse around
http://localhost:4173/en
. - Observe the errors in your console that report things like
Not found: /en/_app/immutable/start-c96f4d66.js
.
Logs
Example of the crawler error when running npm run build
:
Error: Not found: /section/subsection
at resolve (file:///path/to/sveltekit-base-prerendering/.svelte-kit/output/server/index.js:2493:18)
at resolve (file:///path/to/sveltekit-base-prerendering/.svelte-kit/output/server/index.js:2358:34)
at Object.#options.hooks.handle (file:///path/to/sveltekit-base-prerendering/.svelte-kit/output/server/index.js:2537:59)
at respond (file:///path/to/sveltekit-base-prerendering/.svelte-kit/output/server/index.js:2356:43)
file:///path/to/sveltekit-base-prerendering/node_modules/@sveltejs/kit/src/core/postbuild/prerender.js:27
throw new Error(format(details));
^
Error: 404 /section/subsection (linked from /en)
at file:///path/to/sveltekit-base-prerendering/node_modules/@sveltejs/kit/src/core/postbuild/prerender.js:27:11
at save (file:///path/to/sveltekit-base-prerendering/node_modules/@sveltejs/kit/src/core/postbuild/prerender.js:346:4)
at visit (file:///path/to/sveltekit-base-prerendering/node_modules/@sveltejs/kit/src/core/postbuild/prerender.js:195:3)
[vite-plugin-sveltekit-compile] Prerendering failed with code 1
error during build:
Error: Prerendering failed with code 1
at ChildProcess.<anonymous> (file:///path/to/sveltekit-base-prerendering/node_modules/@sveltejs/kit/src/exports/vite/index.js:599:15)
at ChildProcess.emit (node:events:513:28)
at Process.ChildProcess._handle.onexit (node:internal/child_process:291:12)
Example of the asset errors after npm run build && npm run preview
in branch assets
:
Error: Not found: /en/_app/immutable/start-c96f4d66.js
at resolve (file:///home/juris/sveltekit-base-prerendering/.svelte-kit/output/server/index.js:2493:18)
at resolve (file:///home/juris/sveltekit-base-prerendering/.svelte-kit/output/server/index.js:2358:34)
at Object.#options.hooks.handle (file:///home/juris/sveltekit-base-prerendering/.svelte-kit/output/server/index.js:2537:59)
at respond (file:///home/juris/sveltekit-base-prerendering/.svelte-kit/output/server/index.js:2356:43)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
System Info
System:
OS: Linux 5.10 Ubuntu 22.04.1 LTS 22.04.1 LTS (Jammy Jellyfish)
CPU: (8) x64 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
Memory: 4.66 GB / 7.61 GB
Container: Yes
Shell: 3.6.0 - /usr/bin/fish
Binaries:
Node: 16.17.0 - ~/.local/share/nvm/v16.17.0/bin/node
npm: 8.15.0 - ~/.local/share/nvm/v16.17.0/bin/npm
npmPackages:
@sveltejs/adapter-static: ^1.0.0 => 1.0.4
@sveltejs/kit: ^1.0.0 => 1.1.1
svelte: ^3.54.0 => 3.55.1
vite: ^4.0.0 => 4.0.4
Severity
serious, but I can work around it
Additional Information
It seems that localization with a path prefix is not really possible unless one is willing to manually import a lang store and add a /{$lang}/
prefix to all internal links.
While some workarounds could be done as outlined above, the best solution would be official support for path prefixes. Be it with base href or other method of prepending the prefix to internal links.
On a related note it would be good to support something like a set of prerendering param values. E.g. I would like to render all my pages for lang in ['', 'en']
even if no internal link points to some of them. Something like the ['*']
in config.kit.prerender.entries
, but with fixed param values. In the case of prefix param it might even be something like ['/*', '/en/*']
in the same config param.