2

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.

Darkbound
  • 3,026
  • 7
  • 34
  • 72
  • Did you properly manage your vercel env variables? – illia chill Jan 06 '22 at 16:42
  • 1
    @illiachill that has nothing to do with it, there are no env variables that I am using for this particular part, for the rest of the app, it has all the variables that it needs. It is deploying and running just fine, just the socket connection is not working. – Darkbound Jan 06 '22 at 19:05

1 Answers1

8

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.

Darkbound
  • 3,026
  • 7
  • 34
  • 72
  • While you can't use a custom server with Vercel, maybe a solution using API routes could work instead? See related question: [How to use Socket.io with Next.js API Routes](https://stackoverflow.com/questions/57512366/how-to-use-socket-io-with-next-js-api-routes). – juliomalves Jan 08 '22 at 18:57
  • 1
    Probably it will work, but then you have to also think about reconnecting all the time, because afaik, vercel have time limit on functions, I think it was a few limits, so I think that what this approach is doing, is its basically holding the request and not ending it, but Vercel will end it for you at some point:)) – Darkbound Jan 15 '22 at 13:10
  • While it's true that it may not be as simple as doing it with a custom server, it's definitely not impossible, though. – juliomalves Jan 15 '22 at 13:12
  • Yeah, but why go through all that hassle, when you can just move to Heroku and do it the normal way:)))) which is what I did:) – Darkbound Jan 16 '22 at 14:25
  • As of writing, heroku no longer provides free dynos anymore so your options are limited – Rod911 Dec 05 '22 at 16:57