Server-side rendering fails with live_svelte v0.16.0 and Svelte 5 because the render() function returns an object with getters that don't serialize properly.
Environment
live_svelte: v0.16.0
svelte: v5.41.2
esbuild-svelte: v0.9.3
- Node.js: v22.20.0
Expected Behavior
Svelte components should render server-side, with the HTML content visible in the page source.
Actual Behavior
Components don't render server-side. The LiveView receives an empty object %{} from NodeJS instead of the rendered HTML.
Root Cause
Svelte 5's render() function from svelte/server returns an object with getters for html, head, and body properties:
Object.defineProperties(result, {
html: { get: () => { ... } },
head: { get: () => { ... } },
body: { get: () => { ... } }
})
When NodeJS.call! serializes this object to send back to Elixir, it only sees {} because property getters aren't enumerable by default.
This appears to be a breaking change in how Svelte 5's render() function returns data compared to Svelte 4. The migration guide in live_svelte's README mentions Svelte 5 support but doesn't mention this issue.
Workaround
Modify assets/js/server.js to explicitly access the getters:
import * as Components from '../svelte/**/*.svelte'
import { getRender } from 'live_svelte'
const renderFn = getRender(Components)
// Wrap the render function to extract the getter values
// Svelte 5's render() returns an object with getters for html/head/body
// which nodejs library doesn't serialize, so we need to access them explicitly
export function render(name, props, slots) {
const result = renderFn(name, props, slots)
return {
html: result.html,
head: result.head,
body: result.body
}
}
Proposed Fix
The getRender() function in live_svelte's source should be updated to handle Svelte 5's getter-based return values. This could be done in the render function provided by live_svelte, similar to the workaround above.
Steps to Reproduce
- Install live_svelte v0.16.0 with Svelte 5
- Create a simple Svelte component in
assets/svelte/test.svelte:
- Render it in a LiveView with SSR enabled:
<.svelte name="test" props={%{}} socket={@socket} />
- Check page source - the component won't be server-rendered
Server-side rendering fails with
live_sveltev0.16.0 and Svelte 5 because therender()function returns an object with getters that don't serialize properly.Environment
live_svelte: v0.16.0svelte: v5.41.2esbuild-svelte: v0.9.3Expected Behavior
Svelte components should render server-side, with the HTML content visible in the page source.
Actual Behavior
Components don't render server-side. The LiveView receives an empty object
%{}from NodeJS instead of the rendered HTML.Root Cause
Svelte 5's
render()function fromsvelte/serverreturns an object with getters forhtml,head, andbodyproperties:When
NodeJS.call!serializes this object to send back to Elixir, it only sees{}because property getters aren't enumerable by default.This appears to be a breaking change in how Svelte 5's render() function returns data compared to Svelte 4. The migration guide in live_svelte's README mentions Svelte 5 support but doesn't mention this issue.
Workaround
Modify
assets/js/server.jsto explicitly access the getters:Proposed Fix
The
getRender()function inlive_svelte's source should be updated to handle Svelte 5's getter-based return values. This could be done in the render function provided by live_svelte, similar to the workaround above.Steps to Reproduce
assets/svelte/test.svelte: