Read if:
- You wanna learn how to use SocketIO with SvelteKit.
Resources
- SvelteKit: Docs
- SocketIo: Docs
- Vite: Docs
- Extending Guide: Live-Chat with SvelteKit and SocketIO
- Video Guide: Using WebSockets With SvelteKit by Joy of Code
Introduction
This is going to be a series, this is first part of the series and from now on in every 2 days I'll release a new part of this series. Where I'm gonna make a fully fledge chat app using SvelteKit, socketIO, Express and maybe redis. This chat app going to have some features like: Making a group for chat, single chat and allow to join private group link using invitation.
Here I'm going to explain hoe to integrate SocketIO in SvelteKit because SvelteKit doesn't have a built-in support for WebSocket and we have to find a way to use SocketIO in the project for development and production.
Setup the project
First setup your SvelteKit project using init.
npm init svelte@latest anonChatApp
cd anonChatApp
npm install
npm run dev -- --open
I'm using Tailwind CSS in this demo. I've already written an article on Using TailwindCSS in SvelteKit to make a Design System : Part One.
Here we will gonna use node
adapter because of SvelteKit doesn't have built-in support for WebSockets. So we can't use auto
adapter which help us to deploy it on vercel which is now out of the scope, we have to deploy it on our sever.
- We are going to install
adapter-node
in our project
npm i -D @sveltejs/adapter-node
- Make the adapter changes in
svelte.config.js
file
import adapter from '@sveltejs/adapter-node';
import preprocess from 'svelte-preprocess';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: [
preprocess({
postcss: true
})
],
kit: {
adapter: adapter()
}
};
export default config;
Adding SocketIO server
Install the dependencies for socket.io
for server, socket.io-client
for client and we also going to need express.
npm i socket.io socket.io-client express
Here We going to make a vite plugin that going to help us with WebSocket in development version.
// webSocketPluginVite.js
import injectSocketIO from './socketIoHandler.js';
export const webSocketServer = {
name: 'webSocketServer',
configureServer(server) {
injectSocketIO(server.httpServer);
}
};
- Above we are importing
injectSocketIO
fromsocketIoHandler.js
. This file handles are all socketIO events e.g. connection, message, error.
// socketIoHandler.js
import { Server } from 'socket.io';
export default function injectSocketIO(server) {
const io = new Server(server);
io.on('connection', (socket) => {
let username = `User ${Math.round(Math.random() * 999999)}`;
socket.emit('name', username);
socket.on('message', (message) => {
io.emit('message', {
from: username,
message: message,
time: new Date().toLocaleString()
});
});
});
console.log('SocketIO injected');
}
That's a normal setup for dev now we have add plugin to our vite.config.js
. So we can use websocket in development.
import { sveltekit } from '@sveltejs/kit/vite';
import { webSocketServer } from './webSocket.js';
/** @type {import('vite').UserConfig} */
const config = {
server: {
port: 3000
},
preview: {
port: 3000
},
plugins: [sveltekit(), webSocketServer]
};
export default config;
Above i have imported our plugin and added to vite plugin configuration which will now run our WebSockets in development mode.
But we have to add more to make it work in production. So, we have to make a build using
node adapter
that we configured in the start.
npm run build
- This will generate a build for your project now we have to extend our SvelteKit server to use WebSockets in it. That's why we needed
express
which is going to help us extend our default server of SvelteKit.
// server.js
import http from 'http';
import express from 'express';
import injectSocketIO from '../socketIoHandler.js';
import { handler } from '../build/handler.js';
const app = express();
const server = http.createServer(app);
// Inject SocketIO
injectSocketIO(server);
// SvelteKit handlers
app.use(handler);
server.listen(3000, () => {
console.log('Running on http://localhost:3000');
});
- Now you can make a build and run it on production which is running on port
3000
.
Adding SocketIO on Client
We already installed the dependency for client side of SocketIO. We gonna add a file in lib
folder webSocketConnection.js
which going to handle our socket connection for client.
import ioClient from 'socket.io-client';
const ENDPOINT = 'http://localhost:3000';
const socket = ioClient(ENDPOINT);
export const io = socket;
In this we are exporting our socket which uses our endpoint which is running in port
3000
.Now we gonna take a look on client uses of SocketIO
<script lang="ts">
import { io } from '$lib/webSocketConnection.js';
import { onMount } from 'svelte';
let textfield = '';
let username = '';
let messages = [];
onMount(() => {
io.on('message', (message) => {
messages = [...messages, message];
});
io.on('name', (name) => {
username = name;
});
});
function sendMessage() {
const message = textfield.trim();
if (!message) return;
textfield = '';
io.emit('message', message);
}
</script>
<div class="h-screen w-screen bg-zinc-800">
<div class="h-full w-full max-w-md mx-auto bg-zinc-500 flex flex-col">
<header
class="px-6 py-4 border-b border-zinc-800 bg-zinc-700 text-white shrink-0 flex items-center justify-between"
>
<span class="font-bold text-xl">My Chat app</span>
<span>{username}</span>
</header>
<div class="h-full w-full p-4">
{#each messages as message}
<div class="bg-zinc-300 rounded-xl rounded-tl-none px-4 py-3 my-4 w-fit">
<span class="flex items-center space-between gap-4">
<b>{message.from}</b>
<i>{message.time}</i>
</span>
{message.message}
</div>
{/each}
</div>
<form
action="#"
on:submit|preventDefault={sendMessage}
class="px-6 py-4 border-t border-zinc-800 bg-zinc-700 text-white shrink-0 flex items-center"
>
<input
type="text"
bind:value={textfield}
placeholder="Type something..."
class="bg-transparent border-none px-4 py-3 w-full"
/>
<button type="submit" class="shrink-0 border border-white rounded-lg px-4 py-3">Send</button>
</form>
</div>
</div>
- As above in
script
section we are importing are client side socket connection and going to use it in our onMount function so we can get all the new messages and a username that is randomly generated on server. For sending message we are using emit insendMessage
function to send message on server and broadcast to all users.
It a basic setup for SocketIO on dev and prod in SvelteKit. We will continue in second part from here. If you wanna suggest some add on functionalities or features for project please comment it down.
Future me writing this, due to SvelteKit going to make some breaking changes in next update.
This is me writing for you. If you wanna ask or suggest anything please put it in comment.
Top comments (13)
Eagerly waiting for the 2nd part
Thanks you for your support. I'll try as soon as possible to write second part after i cover all the sveltekit changes.
I'm looking forward to this
Anyone aware of a github repo with this setup?
Or a github with expressjs server integrated with sveltekit?
I'm trying to spin my own cutom express server but I get errors. It seems that the handlers.js is not passing anything to the expressjs once I add app.use(handlers) after I require handlers.js on top of the express server file of course.
This repo use to be live haven't worked again but you can use it for guide
Going through this in 2023 just wondering is they a better way to do this now? Or ..
It depends on your need. What you wanna work in what is goal with it.
Just for real time conversation on An online platform.
Is it possible without using expressjs like one of the +server files or something similer
not yet. We have to extend it to use web-sockets. It works only for node adapter.
Thanks for the reply..
This is not so good, there is no way to get your sicketio instance into the apps server side code.
the example works but how would I send a server side message from an api call in svelte to all in a room? i need to get access to the io object for this... how can I share it an svelte api?
You can this out