17

I have been using Svelte for a little while and now I have switched to SvelteKit so I can add multiple pages. I want to add some images to my site but I don't know where to put them. In Svelte I would just put them in public/images but there is no public folder with SvelteKit (I set it up with npm init svelte@next my-app if that matters). Would I put them in static?

Thanks!

Anders
  • 663
  • 1
  • 4
  • 14
  • Both is an option, `static` and `lib`. If you want to import them dynamically, you're better off using `lib` (e.g. when they're part of a component). But having a bunch of "dump images" just lying around in `static` is not wrong either. Whatever suits you, I would say. – b2m9 Apr 08 '22 at 09:23
  • 1
    @b2m9 thanks for your comment. How would I reference them if I used `static`? I tried `../../static/image.png` but it didn't work. I also tried looking up how to use a `lib` but I didn't find anything really helpful. Can you please elaborate? – Anders Apr 08 '22 at 18:07
  • 2
    `static` is your root folder after the build step. So when you put an image into `status/img/photo.jpg`, you can reference it via `/img/photo.jpg`. – b2m9 Apr 11 '22 at 09:06
  • @b2m9 what is the opposite of importing images dynamically, i.e. how can an image NOT be part of a component? – David Schneider Sep 30 '22 at 20:45

4 Answers4

35

I added the images in static/images and referenced them with src="/images/photo.jpg" like @b2m9 said and it works perfectly.

Anders
  • 663
  • 1
  • 4
  • 14
  • 1
    One thing to note is that you have to reference this literally with the `src` attribute. I was under the impression that you had to import the image, Vite style. – khaki May 24 '22 at 18:29
  • 1
    Thanks for pointing that out, I didn't even know you could import images. I have updated my answer. – Anders May 25 '22 at 19:37
  • This answer can be improved. See: https://kit.svelte.dev/docs/assets , https://kit.svelte.dev/docs/configuration#files , https://kit.svelte.dev/docs/project-structure – Wtower Mar 05 '23 at 19:07
  • @Wtower that's a bit vague. Probably worth mentioning specifically what you'd add. – mikemaccana Aug 29 '23 at 10:47
26

I recommend putting images under src/lib, not static. For example you could make a src/lib/images or src/lib/assets folder and put them there.

The reason is performance:

For files imported from anywhere under src, at compile time Vite adds a hash to the filename. myImage.png might end up as myImage-a89cfcb3.png. The hash is based on the image contents. So if you change the image, it gets a new hash. This enables the server to send a very long cache expiration to the browser, so the browser can cache it forever or until it changes. It's key-based cache expiration, which IMO is the best kind: cached exactly as long as it needs to be. (Whether the server actually sends the right caching headers in the response may depend on which SvelteKit adapter you use and what host you're on.)

By contrast, images under static don't have a hash added to their name. You can use the static directory for things like robots.txt that need to have a specific filename. Since the filename stays unchanged even if its contents change, these files by necessity end up having a cache-control value that includes max-age=0, must-revalidate and an etag, which means even if the browser caches the image it still has to make a server round-trip to validate that the cached image is correct. This slows down every image on your site.

Usage:

When putting images under src/lib, you reference them like this:

<script>
import img from '$lib/images/img.png';
</script>

<img src={img} alt="Image" />

I recommend simplifying by adding svelte-preprocess-import-assets to your project, which automates the process of importing images and cleans up your code. You write the following and it generates the code above:

<img src="$lib/images/img.png" alt="Image" />
Brian Morearty
  • 2,794
  • 30
  • 35
  • How are you redefining [%sveltekit.assets%](https://github.com/sveltejs/kit/blob/master/documentation/docs/10-getting-started/30-project-structure.md) with this approach or are you ignoring that prop? It's used in the default `app.html` of `create-svelte` – b1lly Jan 23 '23 at 02:33
  • Good question. I'm not redefining %sveltekit.assets%. It's still there for static assets and still references the `static` directory. I just personally wouldn't use it except for favicon and robots.txt. – Brian Morearty Jan 24 '23 at 04:31
  • This doesn't seem to work in SvelteKit using vite `v4.0.0`... – Jack Westmore Feb 06 '23 at 13:43
  • How would i go about if I have lib/images/first/1.jpg and .2.jpg AND lib/images/second/1.jpg and 2.jpg. >> Then I want to have a dynamic route (xyz.com/first) and fetch all images in "first" folder dynamically. Is it OK to use a dynamic impor this way? Or would I lose performance / break something? – userRR Feb 12 '23 at 12:58
  • 1
    @JackWestmore I would try upgrading Vite. It would be strange for it not to work--it's a basic feature of Vite. I'm using it successfully with Vite v4.0.4. – Brian Morearty Feb 13 '23 at 19:36
  • @userRR For your use case I think putting the images under /static is still the best option and just use ` – Brian Morearty Feb 13 '23 at 20:13
  • [Sveltekit documentation](https://kit.svelte.dev/docs/configuration#files) implicitly supports this answer: "`assets?: string;`: a place to put static files that should have stable URLs and undergo no processing, such as `favicon.ico` or `manifest.json`" – Wtower Mar 05 '23 at 18:35
4

As Sveltekit uses Vitejs, there is a easy solution mentioned in Vitejs official web site (Click Here).
First inside the script tag :

<script>
const imgUrl = new URL('./img.png', import.meta.url).href
</script>

then inside your Image tag just use that variable,

<img src="{imgUrl}" alt="" />

or,

<div class=" h-screen w-full" style="background-image: url('{bgUrl}') ;">
</div>

You can import static images from any relative path.

Wtower
  • 18,848
  • 11
  • 103
  • 80
0

there is also svelte-image.

"Svelte image is a pre-processor which automates image optimization using sharp.

It parses your img tags, optimizes or inlines them and replaces src accordingly. (External images are not optimized.)

Image component enables lazyloading and serving multiple sizes via srcset.

This package is heavily inspired by gatsby image.

Kudos to @jkdoshi for great video tutorial to Svelte Image."

-https://github.com/matyunya/svelte-image

Tyler2P
  • 2,324
  • 26
  • 22
  • 31