SvelteKit: dev/build and path problems with static assets referenced in CSS
Asked Answered
W

1

2

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://mcmap.net/q/802009/-tailwind-and-vite-warnings-quot-didn-39-t-resolve-at-build-time-it-will-remain-unchanged-to-be-resolved-at-runtime-quot 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?

Weymouth answered 25/3, 2023 at 18:44 Comment(3)
The argument of the background-image needs to be in quotes. w3schools.com/cssref/pr_background-image.php Have you tried that?Palaestra
@Script Raccoon You remark is right but that doesn't seem to be the problem.Alienist
Fixed by using absolute path like '/img/bg.jpg'.Jansenism
W
4

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?

Weymouth answered 26/3, 2023 at 10:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.