Vite Plugin

The realtime() Vite plugin scans src/live/ and generates $live/* virtual imports.

Setup

// vite.config.js
import { sveltekit } from '@sveltejs/kit/vite';
import uws from 'svelte-adapter-uws/vite';
import realtime from 'svelte-realtime/vite';

export default {
  plugins: [sveltekit(), uws(), realtime()]
};

How it works

  1. The plugin watches src/live/ for .js and .ts files
  2. It parses each file for live(), live.stream(), live.cron(), etc. exports
  3. It generates client stub modules under the $live/ virtual import prefix
  4. live() exports become async RPC functions
  5. live.stream() exports become Svelte store factories
  6. Server-only code is stripped from the client bundle

What gets generated

For a file src/live/chat.js that exports:

  • sendMessage via live()
  • messages via live.stream()

The plugin generates $live/chat with:

  • sendMessage(text) - calls the server function over WebSocket
  • messages - a Svelte store that subscribes to the 'messages' topic

File structure

src/live/
├── chat.js        => $live/chat
├── todos.js       => $live/todos
└── admin/
    └── users.js   => $live/admin/users

Nested directories map to nested import paths.

Options

realtime({ dir: 'src/live', typedImports: true, devtools: true })
OptionDefaultDescription
dir'src/live'Directory containing live modules
typedImportstrueGenerate .d.ts for typed $live/ imports
devtoolstrueEnable the in-browser DevTools overlay in dev mode

When typedImports is enabled, the plugin generates type declarations that strip the ctx parameter and infer return types.

Server-side HMR

Changes to files in src/live/ are hot-reloaded on the server without restarting npm run dev. When you save a file, the plugin:

  1. Invalidates the changed module in Vite’s server module graph
  2. Clears all server-side registrations (RPC handlers, guards, cron jobs, derived streams, effects, aggregates)
  3. Re-imports the registry module so every registration call runs with the updated handler functions

This applies to all handler types - live(), live.stream(), live.cron(), live.derived(), live.effect(), live.aggregate(), live.room(), guard(), and everything else. Adding or deleting files in src/live/ also triggers a full re-registration.

Error recovery: if the edited file has a syntax error, the previous handlers are restored so the server keeps working. Fix the error and save again.

Active subscriptions: existing stream subscribers keep their current data and connection. They will receive new events published by the updated handler, but the init function only runs on new subscriptions. A full page reload picks up the latest init logic.

Cron jobs: old intervals are cleared and restarted with the updated schedule and handler.

Was this page helpful?