JonasKruckenberg / imagetools

Load and transform images using a toolbox :toolbox: of custom import directives!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Query strings don't work in dynamic imports with template literals containing variables

refact0r opened this issue · comments

I am working on a static Sveltekit site.
When I dynamically import an image with

const module = await import(`$lib/images/${name}.jpg?w=400`)

I get
image
It seems to be applying my defaultDirectives:

return new URLSearchParams({
    format: `avif;jpg`,
    w: '2000;1000;500',
    as: 'picture'
})

but the actual directives in the URL don't work.

Probably not the best possible solution,

You can always make defaultDirectives more specific using conditionals as specified in docs under options:

    imagetools({
      defaultDirectives: (url) => {
        if (url.searchParams.has('spotify')) {
          return new URLSearchParams({
            tint: 'ffaa22'
          })
        }
        return new URLSearchParams()
      }
    })

and instead of long string you can use it as your "own" directive.

You can also use more complicated conditions.

I solved it by just appending the rest at the end.

		imagetools({
			defaultDirectives: (url: URL) => {
				const extension = url.pathname.substring(url.pathname.lastIndexOf('.') + 1);
				if (['png', 'jpg', 'jpeg'].includes(extension)) {
					return new URLSearchParams(
						'format=avif;webp;' + extension + '&as=picture&w=2000;1000;500' + url.searchParams
					);
				}
				return new URLSearchParams();
			}
		}),

But i can also imagine ignoring all defaults by using

		imagetools({
			defaultDirectives: (url: URL) => {
				if (url.searchParams.has('custom')) {
					return url.searchParams;
				}
				return new URLSearchParams();
			}
		}),

Thanks, this works as a solution.

But it is still quite weird that with normal imports the default directives are overwritten, but with dynamic imports they are not (at least this was the case when I submitted this issue, I have not tried to reproduce since then).

It would be interesting to see if this is still the case, I remember that dynamic imports are behaving slightly differently to regular imports in vite.

This seems to work for me

Screenshot from 2023-09-21 16-19-41

Can anyone provide a project that reproduces this? Otherwise I'll assume it works and close the issue

@benmccann I think you misunderstood, the problem is that static imports can override the defaultDirectives defined in vite config, but dynamic imports cannot.

I can still reproduce the issue. (repo: https://github.com/refact0r/imagetools-575)

imagetools({
	defaultDirectives: () => {
		return new URLSearchParams({
			blur: '10'
		});
	}
}),
<script>
	import { onMount } from 'svelte';
	import static_image from '../../static/favicon.png?blur=1';

	let dynamic_image;
	let name = 'favicon';

	onMount(async () => {
		dynamic_image = (await import(`../../static/${name}.png?blur=1`)).default;
	});
</script>

<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>

<p>static import</p>
<img src={static_image} alt="Svelte logo" />

<p>dynamic import</p>
<img src={dynamic_image} alt="Svelte logo" />

image

Ok, so there are more parts to this. It's not that you override a defaultDirective, but it's that you use a template literal that has a variable together with a query string. This one will have to be addressed in Vite: vitejs/vite#14449

I'll note that I also hit vitejs/vite#14101 while debugging this

Ah, that makes sense.

This will be fixed in Vite 5. Thanks to @Dunqing for the fix!