SvelteKit with SocketIO in Production
Tags: javascript, svelte, webdev, sveltekit
Published: 2022-07-30 04:14:00

##Read if:
- You wanna learn how to use SocketIO with SvelteKit.

##Resources

- SvelteKit: [Docs](https://kit.svelte.dev/docs/introduction)
- SocketIo: [Docs](https://socket.io/docs/v4/server-api/)
- Vite: [Docs](https://vitejs.dev/config/)
- Extending Guide: [Live-Chat with SvelteKit and SocketIO](https://linu.us/live-chat-with-sveltekit-and-socketio)
- Video Guide: [Using WebSockets With SvelteKit by Joy of Code](https://www.youtube.com/watch?v=mAcKzdW5fR8)

##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.
```bash
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](https://dev.to/theether0/using-tailwindcss-in-sveltekit-to-make-a-design-system-part-one-4k3p).

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

```bash
npm i -D @sveltejs/adapter-node
```
- Make the adapter changes in `svelte.config.js` file
```javascript
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.

```bash
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.

```javascript
// webSocketPluginVite.js 
import injectSocketIO from './socketIoHandler.js';

export const webSocketServer = {
	name: 'webSocketServer',
	configureServer(server) {
		injectSocketIO(server.httpServer);
	}
};
```

- Above we are importing `injectSocketIO` from `socketIoHandler.js`. This file handles are all socketIO events e.g. connection, message, error.

```javascript
// 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.

```Javascript 
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.

```bash 
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.

```Javascript
// 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.

```Javascript 
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

```javascript
<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 in `sendMessage` 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.