Using WebSockets With SvelteKit
Published May 1, 2022
Table of Contents
Using WebSockets
If youโre reading this in the future SvelteKit might have native support for WebSockets similar to how it does HTTP request methods so it might be worth checking the documentation.
// HTTP request methods
export function GET() {}
export function POST() {}
// Doesn't exist yet! ๐
export function WS() {}
You can read the discussion about native support for WebSockets inside SvelteKit if you want.
One solution is to create a separate server but then you have to run two things on separate ports so let me show you how you can do it using SvelteKit instead.
WebSockets For Development
To be able to use WebSockets during development you need to write a simple plugin for Vite using the configureServer method to hook into the development server.
Credit goes to Bob Fanger for the solution.
Install the Node adapter with npm i -D @sveltejs/adapter-node
because itโs required for this to work.
import { sveltekit } from '@sveltejs/kit/vite'
import { type ViteDevServer, defineConfig } from 'vite'
import { Server } from 'socket.io'
const webSocketServer = {
name: 'webSocketServer',
configureServer(server: ViteDevServer) {
if (!server.httpServer) return
const io = new Server(server.httpServer)
io.on('connection', (socket) => {
socket.emit('eventFromServer', 'Hello, World ๐')
})
}
}
export default defineConfig({
plugins: [sveltekit(), webSocketServer]
})
๐ฟ๏ธ Use a dynamic import if you need to import code thatโs not a module inside
webSocketServer
for exampleconst code = await import('./code.js')
otherwise youโre going to encounter an error.
Hereโs an example how this works using Socket.io
on the client.
<script lang="ts">
import { io } from 'socket.io-client'
const socket = io()
socket.on('eventFromServer', (message) => {
console.log(message)
})
</script>
If you start the development server with npm run dev
it should work and you should see the Hello, World ๐
message in the console.
If you want to emit a message when a value changes donโt forget you can use a reactive declaration block.
<script lang="ts">
// ...
$: {
// send message to server
socket.emit('eventFromClient', $reactiveValue)
}
</script>
WebSockets For Production
Thanks to the Sveltekit Node adapter you can create a custom server and do whatever you want.
Iโm going to use Express because itโs a minimal web framework.
npm i express @types/express
The Node adapter creates the index.js
and handler.js
files in your build
folder when you run npm run build
.
To use a custom server you have to import the handler
from build/handler.js
and use the custom server instead of index.js
.
Create the build
folder.
npm run build
I have created the server/index.js
file at the root of the project for convenience but this depends on your build step and where youโre deploying it.
import express from 'express'
import { createServer } from 'http'
import { Server } from 'socket.io'
import { handler } from '../build/handler.js'
const port = 3000
const app = express()
const server = createServer(app)
const io = new Server(server)
io.on('connection', (socket) => {
socket.emit('eventFromServer', 'Hello, World ๐')
})
// SvelteKit should handle everything else using Express middleware
// https://github.com/sveltejs/kit/tree/master/packages/adapter-node#custom-server
app.use(handler)
server.listen(port)
Add the script to start the server inside package.json
.
{
"scripts": {
"start": "node ./server"
// ...
}
}
You can run npm start
and open http://localhost:3000/ to check if everything works.
Thatโs it! ๐ฅณ