svimg icon indicating copy to clipboard operation
svimg copied to clipboard

Breaking Bug due to `outputDir` path. Fix is to remove `static/` prefix from generated URLs.

Open jasongitmail opened this issue 1 year ago • 4 comments

I experience a breaking bug with svimg v3.2.0.

I have tested with both vitePreprocess (SvelteKit's default) and svelte-preprocess and received identical behavior.

To Reproduce

  • Set up svelte.config.js as below
// svelte.config.js
... 
imagePreprocessor({
	inputDir: 'src/lib/images',
	outputDir: 'static/images/g',
	avif: true,
	webp: true,
}),
...
  • Run npm run dev, visit localhost:5173. Images are generated on disk successfully (AVIF, webp, and original file type) and can be found in the project at /static/images/g/<filename.abc123.avif>, etc.
  • However, images in the UI 404 because static is part of the URL, but should not be.
<picture class="svelte-10eg0uz">
  <source
    type="image/avif"
    sizes="900px"
    srcset="static/images/g/example.fa93hs3k.3294a557f2ddbc3d53c32b986b15c384.avif 2432w" />
  <source
    type="image/webp"
    sizes="900px"
    srcset="static/images/g/example.fa93hs3k.3294a557f2ddbc3d53c32b986b15c384.webp 2432w" />
  <img
    sizes="900px"
    width="900"
    alt="something"
    class="image loaded svelte-10eg0uz"
  srcset="static/images/g/example.fa93hs3k.3294a557f2ddbc3d53c32b986b15c384.png
  900w"/>
</picture>
  • This 404's because SvelteKit serves all files found within static at the site's root (without static as part of the file path) and is actually available at images/g/example.fa93hs3k.3294a557f2ddbc3d53c32b986b15c384.avif.

The solution is to not include static as part of the image URLs within the HTML.

System

Node v20.2.0

"svimg": "^3.2.0",
"@sveltejs/kit": "^1.20.2",
"vite": "^4.3.0",
"svelte-preprocess": "^5.0.4",

jasongitmail avatar Jun 08 '23 23:06 jasongitmail

Temporary workaround for development:

  • Set outputDir to NOT include static, so that the image file paths in the HTML do not include static.
// svelte.config.js
... 
imagePreprocessor({
	inputDir: 'src/lib/images',
	outputDir: 'images/g',
	avif: true,
	webp: true,
}),
...
  • Update vite.config.js to allow serving from the images dir in the project root:
export default defineConfig({
        ...
	server: {
		fs: {
			allow: ['images'],
		},
	},
});
  • Restart dev server npm run dev.

  • This does NOT work for production though (npm run build && npm run preview) because Error: Not found: <filename.abc123.avif> occurs for all images processed by svimg.

jasongitmail avatar Jun 08 '23 23:06 jasongitmail

I have just spent 4 hours on this but my issue turned out to be different. Posting in case someone else is also developing on MacOS and deploying to a linux environment.

The src prop was "IMG_something.JPG" but it the actual file name is "IMG_something.jpg". MacOS is not case sensitive so this was working on dev and build locally but in production.

manuganji avatar Jun 14 '23 10:06 manuganji

This is covered a bit in the documentation of the outputDir and srcGenerator preprocessor options. The default behavior to generate the image URI is built around the outputDir being a subdirectory of the inputDir (generally, with your images already existing within your static directory). If this is not the case for you, you can use the srcGenerator callback to manipulate the generated URIs to add/remove/modify path components as needed, because svimg isn't aware of the URI the outputDir ends up being served from.

xiphux avatar Jun 19 '23 21:06 xiphux

Thanks for the response. Up to you if you want to document it differently. FWIW, it would seem more intuitive to make both relative to the project root. I've more recently realized I want output images to be served from _app/immutable and have far-futures caching, so I've switched to a vite-imagetool solution now. But props for making this! It was the only that worked out of the box.

jasongitmail avatar Jul 15 '23 17:07 jasongitmail