Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamically import assets in Sveltekit/Vite #10618

Closed
diramazioni opened this issue Aug 24, 2023 · 5 comments
Closed

Dynamically import assets in Sveltekit/Vite #10618

diramazioni opened this issue Aug 24, 2023 · 5 comments

Comments

@diramazioni
Copy link

diramazioni commented Aug 24, 2023

Describe the problem

I'm asking for alternative ways you may know, in SvelteKit/Vite, to get a list of asset files (in this case images) preferably by hitting an API endpoint like /api/assets/[param]

By using vite's import.meta.glob works only by hard-coding the directory of interest:

  const my_path = "$lib/assets/*.jpg"
  const imageModules = import.meta.glob(my_path); // <- This doesn't work

Invalid glob import syntax: Could only use literals
I know this has been asked before and supposedly a fix was merged but without using switch statement, this still doesn't work!

Only this works:

<script lang="ts"> 
  const imageModules = import.meta.glob("$lib/assets/*.jpg"); 
  const imagePath = Object.keys(imageModules).map((key) => imageModules[key].name.split('/').pop());	
</script>
	{#each imagePath as src }
        <img {src} alt="{src}"/>
    {/each}

Isn't this ugly and impractical to not being able to dynamically set the destination directory? Are there some other ways?

Describe the proposed solution

const imagePath = import.assets(my_dir)

Alternatives considered

(in server.ts)

import { globby } from 'globby';
let paths = await globby(['*', '$lib/assets/*.jpg']);

leads to ReferenceError: paths is not defined (??)

Importance

would make my life easier

Additional Information

Note the part: .name.split('/').pop() I had to add it to get rid of the full path because otherwise it wasn't working once deployed and built.
And this is addition to my svelte.config.js to make the assets available once deployed

		files: {
			assets: './src/lib/assets'
		},

To get to this point I had to crawl many scattered information, I hope it could be of some use to others, and hopefully I'm not aware of other simpler way to get a list of files dynamically!

@ghostdevv
Copy link
Member

ghostdevv commented Aug 24, 2023

I think this issue would be better placed in vite, though I don't believe they would accept it. It's quite deliberate having to put a string literal in import.meta.glob. This is because vite generates these at build time, not at run time. So using a variable here wouldn't work.

The best solution is one you already mentioned: const imageModules = import.meta.glob("$lib/assets/*.jpg");. I think the way to do that, which won't break a build is:

+page.ts

const imageModules = Object.entries(import.meta.glob("$lib/assets/*.jpg"));

export async function load() {
	const images = imageModules
	// apply some filter
    .filter(([key]) => true)
	// import images, if you don't need a filter use { eager: true } to avoid this step
    .map(async ([, fn]) => {
      const image = await fn();
      return image.default;
    });

  return {
    images: await Promise.all(image),
  };
}

+page.svelte

<script>
	export let images;
</script>

{#each images as image}
	<img src={image} />
{/each}

The code might not be perfect as I typed it out in the browser but you hopefully get the idea. I'm gonna close this for now but if you have any more questions let me know 🙏

@ghostdevv ghostdevv closed this as not planned Won't fix, can't repro, duplicate, stale Aug 24, 2023
@diramazioni
Copy link
Author

Thanks for looking into that, I was asking if there are other alternative solutions to do it. I mentioned globby, that doesn't seem to work (why?) Maybe there are other ES modules?. Can a preprocessor or other mechanism be used in place?
I hope I don't have to resort at spawning another server in some other language just to get a list of files dynamically!
I think that sveltekit should address this directly, closing this won't make the problem go away, it's quite a common need also for the idea of independent individual components that may need such a functionality.

@ghostdevv
Copy link
Member

I mentioned globby, that doesn't seem to work (why?)

What adapter are you using? Might not work on your deployment platform, though I don't know as I've never used globby. I personally would still recommend using import.glob but in a few deployment targets you can definitely access the file system. Just make sure you do it in a .server.ts file

@diramazioni
Copy link
Author

I've deployed it on node on my server
Thinking about it again, I can have an import.glob selecting all the assets in the root and filter them afterwards at run time.

@diramazioni
Copy link
Author

I've just realized that import.meta.glob is not updating once the application is deployed.
I've set export const ssr = false; into page.ts but it makes not difference: I see them present in /build/client
So my question remains "How to show images dynamically (that change after build time) ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants