vite-plugin-node
vite-plugin-node copied to clipboard
Websockets do not work
Using the following code, I cannot establish websocket connections:
import Fastify from "fastify";
import wsPlugin from "fastify-websocket";
export const server = Fastify();
server.register(wsPlugin);
server.get("/", { websocket: true }, (ws, req) => {
console.log(req);
ws.socket.on("message", (msg) => {
console.log(msg.toString());
ws.socket.send("hi from server");
});
});
if (process.env.NODE_ENV === "production") {
server.listen(3000);
}
If I run the server directly, it works fine.
vite.config.ts:
import { defineConfig } from "vite";
import { VitePluginNode } from "vite-plugin-node";
export default defineConfig({
server: {
port: 3000,
},
plugins: [
...VitePluginNode({
adapter: "fastify",
appPath: "./src/server.ts",
exportName: "server",
tsCompiler: "esbuild",
}),
],
});
hi @chanced thank you for reporting this. I have to figure out a way to support websocket
@axe-me no problem. Thanks for publishing the package.
I'm just going to roll with esbuild for that package. It makes more sense anyway. I figured I'd let you know, regardless.
Websockets don't seem to work with Express as well
I think it work in production at least for me, I used express.js and socket.io for example (I took the base code from YT called The net ninja repo link: https://github.com/iamshaunjp/websockets-playlist).
what I did is:
- created websocket.ts that export function addWebSocketHandler:
import { Server } from 'http'
import { Server as WSServer } from 'socket.io'
export function addWebSocketHandler(server: Server) {
const io = new WSServer(server, { allowEIO3: true })
io.on('connection', (socket) => {
console.log('made socket connection', socket.id)
// Handle chat event
socket.on('chat', function (data) {
io.sockets.emit('chat', data)
})
// Handle typing event
socket.on('typing', function (data) {
socket.broadcast.emit('typing', data)
})
})
}
- imported it on app.ts:
import { addWebSocketHandler } from './websocket'
- then added it to production if case:
if (process.env.NODE_ENV === 'production') {
const server = app.listen(3000, () => console.log(`server run on: http://localhost:3000`))
if (process.env.WS === 'true') { // a check I added to make sure there is WS handler we want to add in.
addWebSocketHandler(server)
}
}
As for ViteDevServer, I think this is a good way to add it only need to add support in ViteNodeConfig for that. like adding new key called wsPath like the appPath key in the config.
That we can call the function from the file provided in the config and add it to vite dev server although I fairly new to vite so I do not know how to accomplish that.
The WS library also doesn't work. For now I've been using the below work around which uses nodemon to build and run the app on file change. This is obviously not ideal because I lose out on HMR, and have to run the app in production mode locally, but its better than having to manually restart Vite everytime I make a change.
Here is the work around, replace your npm run dev with the following command:
nodemon --exec \"vite build && node dist/main.js\" -e ts --ignore dist/
Any news on this issue?
Hllo,
I think this is not too difficult to work on.
Just like the viteNodeApp export key, there can be added another export default key that receives the web server built by vite. Then the user code can be do anything with it.
Of course, the function should be called every time the HMR runs.
Not sure if it can be done, but here is my suggestion.
I have the same issue. In order for websockets to work the server needs to handle upgrade request, and since vite uses it for live reload, our own ws implementation does not work. I think vite recieves the upgrade event and it does not propograte to our code. It may be very hard to solve this issue, as rewriting vite's behavior is a no go.
Vite is an absolute blessing upon js and ts community, and bringing it to the server is the next step. Typescript project setup is always a pain, and this project solves all the issues.
In the meantime use nodemon.
Hope this can be resolved someday.
For a workaround: nodemon + vite-node
package.json:
// ...
"dev": "nodemon -e \"ts,mts,json\" -x \"vite-node src/server.ts\" -w \"src/**/*\" -i \"**/__tests__/**\"",
"build": "vite build",
"preview": "node dist/server.mjs",
"test": "vitest --coverage",
// ...
vite.config.ts:
// ...
export default defineConfig({
// ...
build: {
ssr: './src/server.ts',
},
// ...
});
My template is here.
@Shyam-Chen What's the benefit of running vite-node if you're just going to restart it via nodemon whenever any of the source files changes?
@svicalifornia No benefit of vite-node in nodemon. I just want to support WebSockets in development.
// ...
"dev": "vite",
"dev:ws": "nodemon -e \"ts,mts,json\" -x \"vite-node src/server.ts\" -w \"src/**/*\" -i \"**/__tests__/**\"",
"build": "vite build",
"preview": "node dist/server.mjs",
"test": "vitest --coverage",
// ...
Ref: https://github.com/vitest-dev/vitest/issues/2334
Use vite-node -w src/server.ts
server.listen({
host: process.env.HOST,
port: process.env.PORT,
});
if (import.meta.hot) {
import.meta.hot.on('vite:beforeFullReload', () => {
server.close();
});
import.meta.hot.dispose(() => {
server.close();
});
}
- "dev": "nodemon -e \"ts,mts,json\" -x \"vite-node src/server.ts\" -w \"src/**/*\" -i \"**/__tests__/**\"",
+ "dev": "vite-node -w src/server.ts",
Reload is faster than nodemon.
Probably not necessary, but I created another minimal repro of this problem before I found this issue.
Feel free to use it for testing: https://github.com/srmagura/ws-test-vite
I had a similar problem when using vite-plugin-node, koa and socket-io and kinda made it work. My solution looks like this (I use the express adapter because it expects a plain http server unlike the koa adapter apparently):
// vite.config.ts
export default defineConfig({
server: {
port: 3000,
},
plugins: [
...VitePluginNode({
adapter: 'express',
appPath: 'src/main.ts',
exportName: 'serverListener',
}),
],
});
// src/main.ts
import Koa from 'koa';
import { createServer } from 'http';
import * as constants from '@/constants';
const application = new Koa();
const server = createServer(application.callback());
const io = new SocketIoServer(server, { /* options */ });
io.on('connection', (socket) => {
// do somethin
});
// Workaround to allow websockets on development using vite-plugin-node
export const serverListener = server.listeners('request')[0];
if (constants.common.ENVIRONMENT === 'production') {
server.listen(3000);
console.log('Running application on http://localhost:3000');
}
I haven't been able to establish connections to ws://localhost:3000 yet, but I can now use the polling transport of socket-io on the dev server, which I previously could not do at all, so I suspect my issue is a different one. Hope someone finds a use for this!
// Add Web Socket Configuration
await app.register(require('@fastify/websocket'), {
options: {
maxPayload: 1048576,
server: app.server
},
});
it is working well in local. once I deployed and configured SSL then it is not working
anyone please help me