Streaming from the Remote
A remote doesn’t have to render all at once. It can stream — send the parts it already
has, show a placeholder for the slow parts, and fill them in as they resolve. Because
<micro-frame> embeds whatever the remote sends, the host gets that streaming for free: the
remote’s placeholder appears, then its real content swaps in — and the host never knows the
remote was doing async work.
Marko streams an <await> on its own: wrap the slow part in a <try> with a
<@placeholder>, and Marko flushes the placeholder first, then the resolved content. Here’s
the remote’s notice doing exactly that (remote/src/routes/fragment/+page.marko):
<try> <await|deal|=new Promise((resolve) => setTimeout(() => resolve("50% off — ends tonight"), 800))> <div>${deal}</div> </await> <@placeholder> <div>Loading the latest deal…</div> </@placeholder></try>(In a real app the promise is an API call; here we fake the delay with a timer.)
On the host side, the <micro-frame> embeds the remote as always — with one change from the
earlier lessons: no client-reorder. With client-reorder, the host buffers the remote’s
output and drops it in all at once, so you’d never see it stream. Without it, the host paints the
remote’s stream in order — so the placeholder shows first, then the deal swaps in.
Watch the Host app preview: the remote’s “Loading the latest deal…” placeholder shows for a beat, then the deal streams in — rendered by the remote, embedded live in the host, which never knew the difference. The notice is still dismissible; its × runs in the browser.
That’s the end of Chapter 1. You’ve embedded a remote, refreshed it from the client, and streamed it — all app federation, all with the remote owning its own render.
- Installing the host app
- Installing the remote app
- Building the remote, then starting both apps