In the CSS section of a Svelte file, suppose I use a background-image:
div { background-image: url(img/bg.jpg); }
The image file is in the static
folder (static/img/bg.jpg). This simple example runs perfectly in dev mode.
If I try to build the project (with adapter-auto), I get a warning:
img/bg.jpg referenced in (...) didn't resolve at build time...
and if I run the app it fails to find the image (at /_app/immutable/assets/img/bg.jpg
).
This answer: https://stackoverflow.com/a/75716822/494979 suggests to define an alias in the vite.config.ts
file:
export default defineConfig({
resolve: {
alias: {
$img: "/static/img",
},
},
});
and change the CSS to:
div { background-image: url($img/bg.jpg); }`
The built project now correctly loads the image (from /_app/immutable/assets
).
But now it doesn't work in dev mode (tries to load the image from /static/img/bg.jpg
instead of /img/bg.jpg
).
The problem would be the same for other assets loaded from the CSS, like fonts (with @import
).
The SvelteKit docs (https://kit.svelte.dev/docs/assets) say: "For assets included via the CSS url() function, you may find vitePreprocess useful.", but I have no idea how.
How can I have a configuration that works for both dev and build, as can be expected?
Here's how I solved the problem, by editing the vite.config.ts
file.
The config object needs to be passed as a function with { mode }
as parameter so we can check the mode (development/production) we're in and set the alias value accordingly.
import { sveltekit } from "@sveltejs/kit/vite";
import { defineConfig } from "vite";
export default defineConfig(({ mode }) => ({
plugins: [sveltekit()],
resolve: {
alias: {
$img: mode === "production" ? "./static/img" : "../img",
},
},
}));
// Config was initially this (worked with build, but not dev):
// export default defineConfig({
// plugins: [sveltekit()],
// resolve: {
// alias: {
// $img: "./static/img",
// },
// },
// });
(I came up with the path ../img
for dev mode after a few tries but that wasn't intuitive).
This still feels a bit like a workaround. In any case, I wonder why SvelteKit doesn't solve this properly by default (in my view, there should be no need for aliases here). Maybe there's a better solution?