svelte-websocket Svelte Themes

Svelte Websocket

svelte-websocket

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:

  • a Vite plugin for vite dev
  • runtime helpers for Node servers such as @sveltejs/adapter-node

What you build

You 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:

  • development, by attaching it to Vite's HTTP server
  • production, by attaching it to your custom Node HTTP server

Installation

npm install svelte-websocket

If your app uses the Vite plugin entrypoint, it should already have vite installed through SvelteKit.

Imports

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.

Quick Start

1. Create your websocket module

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");
  });
}

2. Start it in development

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:

  • module path: src/lib/server/websocket/index.ts
  • export name: webSocketServer

3. Expose it for production

Example: src/hooks.server.ts

import { exposeWebSocketServer } from "svelte-websocket";
import { webSocketServer } from "$lib/server/websocket";

exposeWebSocketServer(webSocketServer);

4. Start it from your Node server

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);

Vite Plugin API

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.

Runtime API

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.

Example for a SvelteKit call/chat app

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);

Notes

  • This package assumes a Node HTTP server.
  • It is aimed at SvelteKit dev servers and Node production servers.
  • It does not include socket.io, ws, or any other websocket library.
  • Your SvelteKit app owns the actual websocket implementation and event handlers.

Troubleshooting

My websocket server starts twice

Pass a stable id to the Vite plugin or to startWebSocketServer.

Vite cannot resolve my websocket module

Set modulePath to the exact module you want Vite to load with ssrLoadModule.

Production cannot find the realtime starter

Make sure exposeWebSocketServer(webSocketServer) runs before your custom Node server tries to read globalThis.startRealtimeServer.

I only need runtime helpers

Import from svelte-websocket or svelte-websocket/websocket, not from svelte-websocket/vite.

Development

Build:

npm run build

Type-check:

npm run check

Smoke-test the packaged exports:

npm test

Top categories

Loading Svelte Themes