sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
78.04k stars 4.08k forks source link

Svelte 5: HMR breaks with conditional rendering within {#if} blocks #12417

Closed OllieJT closed 1 month ago

OllieJT commented 1 month ago

Describe the bug

When an HMR update occurs on a conditionally rendered component, the affected component is removed from the document.

Reproduction

Minimal reproduction: github.com/OllieJT/repro-svelte5-hmr-if-block/

  1. Clone repo and install deps
  2. Start dev server npm run dev and make note of the rendered page.
  3. Edit the markup for one of the conditionally rendered components /src/routes/display-apple.svelte or /src/routes/display-orange.svelte - I just add text to the element contents.
  4. Note that an HMR update occurred, the document updated in the browser... but whichever element you just edited is no-longer visible.

What's interesting is conditional rendering with a component map is unaffected. This appears to specifically be an issue affecting the {#if} block.

Logs

No relevant logs.
`12:35:20 [vite] hmr update /src/routes/display-apple.svelte`

System Info

System:
    OS: macOS 14.4.1
    CPU: (10) arm64 Apple M1 Max
    Memory: 104.13 MB / 32.00 GB
    Shell: 5.9 - /opt/homebrew/bin/zsh
  Binaries:
    Node: 20.11.1 - ~/.nvm/versions/node/v20.11.1/bin/node
    npm: 10.2.4 - ~/.nvm/versions/node/v20.11.1/bin/npm
    pnpm: 9.4.0 - ~/Library/pnpm/pnpm
  Browsers:
    Chrome: 126.0.6478.127
    Safari: 17.4.1
  npmPackages:
    svelte: ^5.0.0-next.1 => 5.0.0-next.182

Severity

blocking all usage of svelte

OllieJT commented 1 month ago

A little further clarification to how this repro is set up, and which files are relevant.

Conditional Svelte Component Typical svelte component that accepts props.

# Example
/src/routes/display-apple.svelte
/src/routes/display-orange.svelte

Switch Component - with {#if} block A component that accepts a discriminated union, and renders a component for each case using the {#if} block.

# Example
/src/routes/conditional-with-if.svelte

Switch Component - with {#if} block A component that accepts a discriminated union, and renders a component for each case using a component map and <svelte:component /> element.

# Example
/src/routes/conditional-with-map.svelte

Page Component Loops over data, using the switch component to conditionally render the correct component.

# Example
/src/routes/+page.svelte
dummdidumm commented 1 month ago

Likely same underlying reason as for #12403