vite-plugin-node icon indicating copy to clipboard operation
vite-plugin-node copied to clipboard

Websockets do not work

Open chanced opened this issue 4 years ago • 16 comments
trafficstars

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",
		}),
	],
});

chanced avatar Oct 21 '21 04:10 chanced

hi @chanced thank you for reporting this. I have to figure out a way to support websocket

axe-me avatar Oct 21 '21 16:10 axe-me

@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.

chanced avatar Oct 21 '21 16:10 chanced

Websockets don't seem to work with Express as well

dhkatz avatar Nov 13 '21 05:11 dhkatz

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:

  1. 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)
		})
	})
}
  1. imported it on app.ts:
import { addWebSocketHandler } from './websocket'
  1. 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.

shaif-dorIT avatar Feb 17 '22 12:02 shaif-dorIT

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/

jordanranson avatar Feb 26 '22 18:02 jordanranson

Any news on this issue?

datyin avatar Mar 28 '22 10:03 datyin

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.

francipvb avatar Jul 03 '22 03:07 francipvb

Not sure if it can be done, but here is my suggestion.

francipvb avatar Jul 03 '22 03:07 francipvb

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.

romanzy313 avatar Jul 17 '22 04:07 romanzy313

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 avatar Oct 07 '22 08:10 Shyam-Chen

@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 avatar Jan 17 '23 02:01 svicalifornia

@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",
// ...

Shyam-Chen avatar Jan 18 '23 01:01 Shyam-Chen

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.

Shyam-Chen avatar Feb 03 '23 07:02 Shyam-Chen

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

srmagura avatar May 03 '23 19:05 srmagura

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!

daleal avatar May 15 '23 02:05 daleal

        // 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

tamilv avatar Feb 25 '24 10:02 tamilv