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

astro dev & astro build crash with Unknown file extension ".svg" when importing an SVG inside a dependency #12299

Closed
1 task
codethief opened this issue Oct 24, 2024 · 8 comments
Labels
needs response Issue needs response from OP

Comments

@codethief
Copy link

codethief commented Oct 24, 2024

Astro Info

pnpm exec astro info
Astro                    v4.16.7
Node                     v20.14.0
System                   Linux (x64)
Package Manager          pnpm
Output                   static
Adapter                  none
Integrations             @astrojs/vue

If this issue only occurs in one browser, which browser is a problem?

/

Describe the Bug

I have a Vue component library in which some components import SVG files as ?url, so that they can be used inside e.g. <svg><use href="…" /></svg>. In that library, as a workaround for vitejs/vite#3295 and vitejs/vite#4454, I have manually configured Vite to emit the SVGs as standalone asset files and preserve the ?url imports inside the emitted .js files.

My Astro project depends on that library. But when I import one of those components that import an SVG, astro dev and astro build fail with

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".svg" for […]/vitejs-vue-component-library-with-assets/astro-consumer/node_modules/.pnpm/my-library@[email protected]/node_modules/my-library/dist/assets/logo.svg
    at Object.getFileProtocolModuleFormat [as file:] (node:internal/modules/esm/get_format:160:9)
    at defaultGetFormat (node:internal/modules/esm/get_format:203:36)
    at defaultLoad (node:internal/modules/esm/load:143:22)
    at async ModuleLoader.load (node:internal/modules/esm/loader:396:7)
    at async ModuleLoader.moduleProvider (node:internal/modules/esm/loader:278:45)

Interestingly, this error does not occur if I pnpm link the library into my Astro project (as opposed to installing the tarball or literally copying the library folder into my Astro project's node_modules).

What's the expected result?

The SVG import should work as expected. Notably, it works fine if I use a pure Vite dev server without Astro, see /consumer in the repo linked below. Moreover, in my real-life Astro project things worked fine when I didn't transpile the library components to JS first and instead exposed the raw Vue components and imported them in my Astro project. (However, this is not an option for us for various reasons.)

Link to Minimal Reproducible Example

https://github.com/codethief/vitejs-vue-component-library-with-assets/tree/7e12eb72ef59036992976cf892f0fda583f141a0?tab=readme-ov-file#caveat-in-astro-consumer

Impact

We have dozens of SVGs in our library and cannot possibly inline them in our Vue components because

  • Most SVGs have id attributes, so using (inlining) the same SVG twice on the same page will produce ID collisions which has led to hard-to-track-down bugs in the past.
  • Inlining SVGs affects HTTP response sizes and prevents SVGs from being cached by the browser. -> Affects network & page load performance.
  • Inlining SVGs on pages that render hundreds of icons dramatically affects rendering/hydration performance (to the point where some of our components would take several seconds to hydrate).

In other words: For us there is simply no way around keeping SVGs in separate asset files. The present bug currently prevents this from working, unfortunately. If anyone happens to have a workaround, please let me know!

Participation

  • I am willing to submit a pull request for this issue.
@github-actions github-actions bot added the needs triage Issue needs to be triaged label Oct 24, 2024
@ematipico
Copy link
Member

This feels like an issue with how you set up your monorepo, I am not sure this is an Astro issue. As you said, using pnpm link fixed the issue, so probably there's something incorrect with how you sep your monorepo and your dependencies/peer dependencies.

@ematipico ematipico added needs response Issue needs response from OP and removed needs triage Issue needs to be triaged labels Oct 25, 2024
@bluwy
Copy link
Member

bluwy commented Oct 25, 2024

When you're linking or copying the library locally, you're doing the inverse of https://vite.dev/guide/dep-pre-bundling.html#monorepos-and-linked-dependencies. The issue here is that since the component library uses bundler specific features, like importing SVGs, that library needs to be processed by the bundler.

By default, that does not happen as most libraries are generic and work everywhere, however to opt-in a library to be processed by the bundler, you can configure vite.optimizeDeps.exclude: ['the-library-name'] or vite.ssr.noExternal: ['the-library-name']. The former applies to the browser so it's not prebundled by Vite, the latter applies to the server-side so it's not externalized (loaded by plain node).

@codethief
Copy link
Author

@ematipico I don't think it's a monorepo issue. The issue shows up when I install the library from a tarball, not from the monorepo / a relative path. Besides, my actual setup is not a monorepo in the first place. I just put every together in a single repo for the purposes of providing a reproducing example.

@codethief
Copy link
Author

codethief commented Oct 27, 2024

@bluwy

The issue here is that since the component library uses bundler specific features, like importing SVGs, that library needs to be processed by the bundler.

Yes, that was a conscious decision because all our downstream projects use Vite. And in a pure Vite project it does work, it's only in Astro projects (and only in the dev server) where it's failing.

In any case, thanks for your suggestions! I will give them a try! That being said, can you make sense of the fact that everything works fine in a regular Vite/Vue project and also in an Astro/Vite/Vue production build but not in the Astro dev server?

@codethief
Copy link
Author

codethief commented Oct 29, 2024

In any case, thanks for your suggestions! I will give them a try!

Following up on this, it seems adding the library to the downstream project's ssr.noExternal setting indeed does the trick! However, I still want to do some further testing, so consider this a preliminary report. Besides, I'm still surprised the production build worked without ssr.noExternal and in a pure Vite project (without Astro) there was no issue, either, so I'd still like to understand this better.

@bluwy
Copy link
Member

bluwy commented Oct 31, 2024

With Astro, both dev and build didn't work for me without ssr.noExternal.

For plain Vite, it works because you'd eventually bundle everything for the browser, so SVG imports get transformed on the way during build. In dev, usually you have to specify optimizeDeps.exclude for your library, but I think it coincidentally worked because you're not using some Vite features that would've triggered it, so not having that also worked in dev in Vite.

@bluwy
Copy link
Member

bluwy commented Nov 4, 2024

I don't think there's a fix possible in Astro for this, so I'll close this for now. But feel free to continue the discussion here if you have any questions.

@bluwy bluwy closed this as completed Nov 4, 2024
@codethief
Copy link
Author

@bluwy

With Astro, both dev and build didn't work for me without ssr.noExternal.

I checked again and, yeah, you're right – the behavior is indeed consistent!

For plain Vite […] I think it coincidentally worked

I'm not sure I fully understand but given that the Vite docs are very clear about the fact that I should set vite.ssr.noExternal I think I'm happy for now. Thanks so much for clearing this up!

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

No branches or pull requests

4 participants
@codethief @ematipico @bluwy and others