This repository demonstrates how to set up a Single Page Application (SPA) using Vite, integrated with a Nitro server, and demonstrates how to use Socket.IO and WebSockets (WS) for real-time communication.
In development, the project overwrites Nitros dev preset and uses a custom Node preset in production to enable passing upgrade requests to route handlers. The built in websocket support with crossws is disabled.
Socket.IO is a bit tricky because it expects to be passed an http server instance. For production, it would be possible to make the server accessible, but there doesn't seem to be a way to do that in development because of the way Nitro works under the hood, with a listhen instance and worker running the actual server code.
A solution I settled with is to pass a Node HTTP server instance to Socket.IO without starting it, and manually emit the request
and upgrade
events on the server instance.
export default lazyEventHandler(() => {
const { httpServer } = useSocketIOServer();
return eventHandler(event => {
event.headers.get("upgrade") === "websocket"
? httpServer.emit("upgrade", event.node.req, event.node.req.socket, Buffer.alloc(0))
: httpServer.emit("request", event.node.req, event.node.res);
event._handled = true;
});
});
Nothing special here, using the handleUpgrade
function of WS in the ws server route.
In development, the Nitro renderer proxies requests with httpxy to Vite, while in production, it returns the content of index.html
.
Clone the repository and install the necessary dependencies:
git clone https://github.com/edivados/nitro-spa.git
cd nitro-spa
npm install
To start the development server, run the following command:
npm run dev
This will start the Vite server along with the Nitro server.
npm run build
npm run preview