Search code examples
websocketsocket.ionext.jsvercel

SocketIO with Nextjs deployed to Vercel, socket is not connecting


I am trying to create a next app that also communicates with its backend in realtime with a socket, and I am using socket.io for that. It is all working just fine locally (even when built), but when deployed to vercel, I get errors of the type of WebSocket connection to '<URL>' failed: WebSocket is closed before the connection is established.

First I created a custom Nextjs server:

import { createServer } from "http";
import { parse } from "url";
import { Server as SocketIOServer, Socket } from "socket.io";
import next from "next";

const port = parseInt(process.env.PORT || "3000", 10);
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();

console.log("hello");

app.prepare().then(() => {
  const server = createServer((req, res) => {
    const parsedUrl = parse(req.url!, true);
    handle(req, res, parsedUrl);
  }).listen(port);

  // tslint:disable-next-line:no-console
  console.log(
    `> Server listening at http://localhost:${port} as ${
      dev ? "development" : process.env.NODE_ENV
    }`
  );

  const socketIO = new SocketIOServer(server, { transports: ["websocket"] });

  socketIO.on("connection", (socket: Socket) => {
    console.log("connected", socket.id);
  });
});

Then on the frontend:

import { io } from "socket.io-client";

useEffect(() => {
  const socket = io(window?.location?.hostname || "http://localhost:3000", {
    reconnectionDelay: 1000,
    reconnection: true,
    reconnectionAttempts: 10,
    transports: ["websocket"],
    agent: false,
    upgrade: false,
    rejectUnauthorized: false
  });

  socket.on("connect", () => {
    console.log("someone connected: ", socket?.id);
  });
}, []);

This code works just great locally, no issues at all, both in dev mode and build && start, both work just fine.

The problems start, once it is deployed to vercel.

If I do not add ":3000" to the window.location.hostname I get error:

WebSocket connection to 'wss://xxxxxx.vercel.app/socket.io/?EIO=4&transport=websocket' failed: doOpen

If I add it, then it becomes:

WebSocket connection to 'wss://xxxxxx.vercel.app:3000/socket.io/?EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established.


Solution

  • The answer is:

    It is not possible. Vercel does not support the custom server functionality that Nextjs has. Shame.

    The problem is not in the socket itself, the problem is in Vercel and it doesnt work for the above reason.

    Whoever is having similar problems, the easiest workaround I found is to simply move to Heroku, they are easy enough to set up (I was headed to DO, GCP, AWS and so on, but they all are more time consuming to set up and more complex, for someone who is not a DevOps guy). So I got up and running in a few minutes with Heroku and the custom server is now working.