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

Snippet import breaks dev server on first run after npm install #1066

Open
glupi-borna opened this issue Jan 13, 2025 · 7 comments
Open

Snippet import breaks dev server on first run after npm install #1066

glupi-borna opened this issue Jan 13, 2025 · 7 comments
Labels
bug Something isn't working

Comments

@glupi-borna
Copy link

Describe the bug

Exporting a snippet from one file, importing it in another file and assigning it to a variable causes the dev server to break on first run after npm install.

Hopefully this is the right place to report this issue!

Reproduction URL

https://github.com/glupi-borna/svelte-snippet-bug-repro

Reproduction

The reproduction repo is fairly minimal (and has a readme with steps), but to recreate it from scratch:

Create a new project via npm create vite@latest (both Svelte+TS and Svelte+JS have this issue).

In src/Snippet.svelte:

<script module lang="ts">
   export { foo };
</script>

{#snippet foo()}
{/snippet}

In src/App.svelte:

<script lang="ts">
   import { foo } from "./Snippet.svelte";
   let bar = foo;
</script>

Now run npm install, and then npm run dev.
The dev server should report an error.

Logs

Forced re-optimization of dependencies

  VITE v6.0.7  ready in 213 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help
Error:   Failed to scan for dependencies from entries:
  /home/borna/projects/svelte/repro/index.html

  ✘ [ERROR] No matching export in "html:/home/borna/projects/svelte/repro/src/Snippet.svelte" for import "foo"

    script:/home/borna/projects/svelte/repro/src/App.svelte?id=0:2:12:
      2 │    import { foo } from "./Snippet.svelte";~~~


    at failureErrorWithLog (/home/borna/projects/svelte/repro/node_modules/esbuild/lib/main.js:1476:15)
    at /home/borna/projects/svelte/repro/node_modules/esbuild/lib/main.js:945:25
    at runOnEndCallbacks (/home/borna/projects/svelte/repro/node_modules/esbuild/lib/main.js:1316:45)
    at buildResponseToResult (/home/borna/projects/svelte/repro/node_modules/esbuild/lib/main.js:943:7)
    at /home/borna/projects/svelte/repro/node_modules/esbuild/lib/main.js:955:9
    at new Promise (<anonymous>)
    at requestCallbacks.on-end (/home/borna/projects/svelte/repro/node_modules/esbuild/lib/main.js:954:54)
    at handleRequest (/home/borna/projects/svelte/repro/node_modules/esbuild/lib/main.js:647:17)
    at handleIncomingPacket (/home/borna/projects/svelte/repro/node_modules/esbuild/lib/main.js:672:7)
    at Socket.readFromStdout (/home/borna/projects/svelte/repro/node_modules/esbuild/lib/main.js:600:7)

System Info

System:
    OS: Linux 6.6 Void
    CPU: (24) x64 AMD Ryzen 9 7900X 12-Core Processor
    Memory: 22.96 GB / 30.51 GB
    Container: Yes
    Shell: 5.2.32 - /bin/bash
  Binaries:
    Node: 20.16.0 - /usr/bin/node
    npm: 10.8.1 - /usr/bin/npm
  Browsers:
    Chromium: 130.0.6723.69
  npmPackages:
    @sveltejs/vite-plugin-svelte: ^5.0.3 => 5.0.3
    svelte: ^5.15.0 => 5.17.3
    vite: ^6.0.5 => 6.0.7
@glupi-borna glupi-borna added bug Something isn't working triage Awaiting triage by a project member labels Jan 13, 2025
@dominikg
Copy link
Member

let bar = foo;

seems to be essential to trigger the error message, removing it and only using {@render foo()} in the template of App.svelte works as expected.

It is related to vites optimizer, starting it with vite dev --force causes it every time.

cc @bluwy

@dominikg dominikg removed the triage Awaiting triage by a project member label Jan 13, 2025
@dominikg
Copy link
Member

also happens with vps4 / vite5

@bluwy
Copy link
Member

bluwy commented Jan 14, 2025

The issue is of snippets being a hidden/special variable in the module script once it's declared in the markup. In Vite's scanner, it takes the content of <script module> as is and re-exports them without accounting for the snippet, so the code roughly becomes:

// Snippet.svelte (what vite's scanner sees as it loosely transpile to JS)

export { foo } // from <script module>

export default {} // emulate default exported component

Here's an esbuild playground that illustrates the internal files too.

I guess if we want to fix this, we have to kinda regex-search for all {#snippet XXX} and shim a const XXX = {} in <script module> to workaround this. Probably only fixable directly in Vite.

@dominikg
Copy link
Member

not sure we have to, as long as you don't use the import in a script block but just reference it in template, it'll be ignored.

so if you rename it in the import instead of let bar = foo, it works.

<script>
import {foo as bar} from './Snippet.svelte'
</script>
{@render bar()}

@glupi-borna
Copy link
Author

not sure we have to, as long as you don't use the import in a script block but just reference it in template, it'll be ignored.

so if you rename it in the import instead of let bar = foo, it works.

<script>
import {foo as bar} from './Snippet.svelte'
</script>
{@render bar()}

This works as long as you don't actually need to do something with the snippet in the script block, like pass it to a function, store it in an array, etc. However, I originally ran into this because I want to store the snippet in an object and use it later.

I guess if we want to fix this, we have to kinda regex-search for all {#snippet XXX} and shim a const XXX = {} in <script module> to workaround this. Probably only fixable directly in Vite.

I wouldn't mind dedicating some time to fixing this if I could get some guidance on where to start looking!

@dominikg
Copy link
Member

wonder if you can trick it with an indirection

foo-reexport.js

import * as x from './Snippet.svelte;
export const foo = x.foo ?? 'whatever';
import {foo} from './foo-reexport.js'
...

not ideal but could unblock you in this situation

@glupi-borna
Copy link
Author

Yep, that works, good idea!

In the meanwhile, I did manage to find a different workaround that works for me (I just run the dev server once during the creation of my docker image, and then immediately shut it down -- since the container is only used for local development, it doesn't matter much, and prod builds don't use the dev server anyway), but this is a much cleaner solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants