Small helpers for attaching a websocket server to a SvelteKit app in both development and production.
This package does not define your events or socket protocol. Your app keeps that logic. The package only handles the bootstrapping layer:
vite dev@sveltejs/adapter-nodeYou provide a function that accepts a Node HTTP server:
import type { Server } from "node:http";
export function webSocketServer(server: Server) {
// Attach socket.io, ws, or another websocket implementation here.
}
The same function can then be started in:
npm install svelte-websocket
If your app uses the Vite plugin entrypoint, it should already have vite installed through SvelteKit.
Use separate imports for development and runtime:
import { svelteKitWebSocketPlugin } from "svelte-websocket/vite";
import { exposeWebSocketServer } from "svelte-websocket";
Available entrypoints:
svelte-websocket
Runtime-safe helpers only.svelte-websocket/vite
The Vite development plugin.svelte-websocket/websocket
Same runtime helpers as the root entrypoint.The root entry is intentionally runtime-safe, so importing it in server code does not pull Vite into production.
Example: src/lib/server/websocket/index.ts
import { Server } from "socket.io";
import type { Server as HttpServer } from "node:http";
export function webSocketServer(httpServer: HttpServer) {
const io = new Server(httpServer, {
cors: { origin: "*" }
});
io.on("connection", (socket) => {
socket.emit("welcome", "Realtime server connected");
});
}
Example: vite.config.ts
import { defineConfig } from "vite";
import { sveltekit } from "@sveltejs/kit/vite";
import { svelteKitWebSocketPlugin } from "svelte-websocket/vite";
export default defineConfig({
plugins: [sveltekit(), svelteKitWebSocketPlugin()]
});
Default plugin behavior:
src/lib/server/websocket/index.tswebSocketServerExample: src/hooks.server.ts
import { exposeWebSocketServer } from "svelte-websocket";
import { webSocketServer } from "$lib/server/websocket";
exposeWebSocketServer(webSocketServer);
Example with a custom adapter-node server:
import express from "express";
import { createServer } from "node:http";
import { handler } from "./build/handler.js";
const app = express();
const server = createServer(app);
const startRealtimeServer = globalThis.startRealtimeServer;
if (startRealtimeServer) {
await startRealtimeServer(server);
}
app.use(handler);
server.listen(3000);
svelteKitWebSocketPlugin({
modulePath: "src/lib/server/realtime/index.ts",
exportName: "startRealtimeServer",
id: "realtime-server",
exitOnError: true
});
Options:
modulePath
Path passed to Vite's ssrLoadModule.exportName
Export name expected from that module.id
Optional deduplication id for startup.exitOnError
Whether Vite should exit if websocket startup fails.exposeWebSocketServer(webSocketServer, options?)Exposes your websocket bootstrap function on globalThis.
Default key:
"startRealtimeServer"
You can override the key:
exposeWebSocketServer(webSocketServer, {
globalKey: "myRealtimeBootstrap"
});
getExposedWebSocketServer(options?)Reads the exposed websocket bootstrap function back from globalThis.
startWebSocketServer(httpServer, webSocketServer, options?)Starts a websocket server once per HTTP server instance. If called again with the same id, it returns false instead of starting the same server twice.
This package fits a structure like:
// src/lib/server/websocket/index.ts
export function webSocketServer(httpServer) {
// socket.io events
}
// vite.config.ts
import { svelteKitWebSocketPlugin } from "svelte-websocket/vite";
plugins: [sveltekit(), svelteKitWebSocketPlugin()];
// src/hooks.server.ts
import { exposeWebSocketServer } from "svelte-websocket";
import { webSocketServer } from "$lib/server/websocket";
exposeWebSocketServer(webSocketServer);
socket.io, ws, or any other websocket library.Pass a stable id to the Vite plugin or to startWebSocketServer.
Set modulePath to the exact module you want Vite to load with ssrLoadModule.
Make sure exposeWebSocketServer(webSocketServer) runs before your custom Node server tries to read globalThis.startRealtimeServer.
Import from svelte-websocket or svelte-websocket/websocket, not from svelte-websocket/vite.
Build:
npm run build
Type-check:
npm run check
Smoke-test the packaged exports:
npm test