DEV Community

Cover image for How to use Socket.io with Next.js, Express and TypeScript (ES6 import instead of require statements)
James Wallis
James Wallis

Posted on • Updated on • Originally published at wallis.dev

How to use Socket.io with Next.js, Express and TypeScript (ES6 import instead of require statements)

I'm currently working on a TypeScript project that is using Socket.io to communicate between a Next.js frontend and a custom Express server backend.

While setting up Socket.io I struggled to find documentation explaining how you could set up Socket.io in a TypeScript project using the ES6 import syntax rather than require. It was even more difficult to find anything that explained how it should all fit together with Next.js.

And so this post was born...

If you're starting from scratch...

If you want to make a TypeScript/Express custom server Next.js project, mine was created by combining the custom Express Server example and custom TypeScript Server example located in the Next.js repository.

First I created the project using the command npx create-next-app --example custom-server-typescript to create the custom TypeScript server. Then I retrofitted Express into it by looking at the custom Express server example. The resulting server.ts is at the bottom of this post.

Why didn't I follow another example?

Most of the examples I saw online want you to do something like the following:

import express from 'express';

const app = express();
const server = require('http').Server(app);
const io = require('socket.io')(server);
Enter fullscreen mode Exit fullscreen mode

But I didn't want two or any random require statements in my TypeScript code if I thought they could be avoided.

 My server.ts with only ES6 import

The dependencies you need (In addition to Next.js/React/TypeScript):

npm install -s express @types/express socket-io
Enter fullscreen mode Exit fullscreen mode

The code you've been waiting for:

import express, { Express, Request, Response } from 'express';
import * as http from 'http';
import next, { NextApiHandler } from 'next';
import * as socketio from 'socket.io';

const port: number = parseInt(process.env.PORT || '3000', 10);
const dev: boolean = process.env.NODE_ENV !== 'production';
const nextApp = next({ dev });
const nextHandler: NextApiHandler = nextApp.getRequestHandler();

nextApp.prepare().then(async() => {
    const app: Express = express();
    const server: http.Server = http.createServer(app);
    const io: socketio.Server = new socketio.Server();
    io.attach(server);

    app.get('/hello', async (_: Request, res: Response) => {
        res.send('Hello World')
    });

    io.on('connection', (socket: socketio.Socket) => {
        console.log('connection');
        socket.emit('status', 'Hello from Socket.io');

        socket.on('disconnect', () => {
            console.log('client disconnected');
        })
    });

    app.all('*', (req: any, res: any) => nextHandler(req, res));

    server.listen(port, () => {
        console.log(`> Ready on http://localhost:${port}`);
    });
});
Enter fullscreen mode Exit fullscreen mode

server.ts explanation

The main difference between my server.ts and the ones produced by the Next.js examples is the use of the http module to run the server whereas before Express ran it. This is required so that Socket.io can attach to the server once it's setup.

Additional changes:

  • Changed app to be nextApp so that it is clearer that it was a next app, also changed handler to nextHandler for the same reason. In addition, it's the convention to use the app variable with Express.
  • Used http.CreateServer() rather than const server = require("http").Server(app); to create the HTTP server.
  • Used io.attach() to attach to the HTTP server rather than using require e.g. const io = require("socket.io")(server);.

 Summary

This post demonstrates how to use Socket.io with a Next.js custom server using ES6 import rather than require.

If this post helped you drop me a reaction! Found something I could improve? Let me know in the comments.

Thanks for reading!

Discussion (7)

Collapse
huydhoang profile image
Huy

Good article, just one detail should be fixed:

npm install express socket.io
npm install -D @types/express
Enter fullscreen mode Exit fullscreen mode

Installing socket-io instead of socket.io will give you error. And @types/express should be saved in devDependencies, by convention.

Collapse
mdirshaddev profile image
Md Irshad

I was struggling to use socket.io with es6. Thanks for providing solution

Collapse
jameswallis profile image
James Wallis Author

Thanks, happy I could help!

Collapse
youneshenni profile image
Henni Younes

Amazing! Combining this template with ESLint, a logger and Jest would make it just perfect! Thanks

Collapse
stevereid profile image
Steve Reid

Awesome! This is exactly what I was looking for 👍🏾😀

Collapse
jameswallis profile image
James Wallis Author

Thanks!

Collapse
timbicker profile image
Tim Bicker

nice, very helpful!