How to Create VueJs App With WebSocket Server on Same Port - javascript

I'm a bit of a JS and Vue noob and I'm trying to figure out how to run my Vue app and a websocket server for that app on the same port 80 (to later be put behind a reverse proxy). I am able to get this working as a simple http server with express, but I can't figure out how to do it with my Vue use case.
My goal is to run a single main.js with npm run serve and bind the websocket server and routes I'm setting up with the vue router all in one application, on the same port.
Here is the example for the simple HTTP case:
server.js
'use strict';
let fs = require('fs');
let express = require('express');
let app = express();
let bodyParser = require('body-parser');
let WSServer = require('ws').Server;
let server = require('http').createServer();
let PORT = 8080
app.use(bodyParser.json());
// regular HTTP request and response
app.get('/', function(req, res) {
console.log('Get index');
fs.createReadStream('./index.html').pipe(res);
});
app.post('/', function(req, res) {
let message = req.body.message;
console.log('Regular POST message: ', message);
return res.json({ answer: 42 });
});
module.exports = app;
// Create web socket server on top of a regular http server
let wss = new WSServer({ server: server });
// Also mount the app here
server.on('request', app);
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log(`received: ${message}`);
ws.send(JSON.stringify({ answer: 42 }));
});
});
server.listen(PORT, function() {
console.log(`http/ws server listening on ${PORT}`);
});
But my question is how can I modify the default main.js vue file to do this?
import { createApp } from 'vue';
import App from './App.vue';
---
import router from './router';
import store from './store';
createApp(App).use(store).use(router).mount('#app');

Related

Refresh issue when serving create-react-app with Express.js

hope you are well!
I have an issue when trying to serve a create-react-app using an express.js server with Node.js backend.
For backend I have some routes defined to create an API with express and prisma, connecting to a database.
For frontend I used a react based app, Axios to fetch data from backend and react-router-dom V6 for client routing (BrowserRouter). To serve the files I created a build folder from React (in the .env file I have INLINE_RUNTIME_CHUNK set to false) with the npm run build script.
The files are generated correctly for the build and from the express app I attach these interface files with the separate route along with the API routes I have already defined. Everything goes okay, the interface opens, the API works but only if I navigate using components in the interface.
When I refresh a page in the browser, the application suddenly stops rendering, under a white screen. In the console area, in DevTools all kinds of loading errors appear which I will attach below with a print screen. The same thing happens if I try to navigate to another route in the browser bar.
I want to launch the application with express on an IP from a local machine. The server code is attached below with the required routes and middleware. So is the axios code and the routing in the interface. Has anyone else had problems like this?
import axios from 'axios';
const publicFetch = axios.create({
baseURL: "http://ABC.ABC.0.ABC:3002/api-v1"
});
export default publicFetch;
An this is the server code:
'use strict';
require('dotenv').config();
const express = require('express');
const path = require('path');
const morgan = require('morgan');
const helmet = require('helmet');
const cors = require('cors');
const compression = require('compression');
const SERVER_PORT = process.env.SERVER_PORT;
// ================================================
// Server routes/controllers
// ================================================
const { createUser, getAllUsers, getSingleUser, updateUser, deleteUser, loginUser } = require('./routes/user-routes');
const { createDepartment, getAllDepartments, getSingleDepartment, updateDepartmentData, deleteDepartment } = require('./routes/department-routes');
const whitelist = ['ABC.ABC.0.ABC'];
const corsOptions = {
origin: function (origin, callback) {
if (!origin || whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
}
// ================================================
// Express App
// ================================================
const app = express();
app.enable('trust proxy');
// CORS
app.use(cors(corsOptions));
// JSON
app.use(express.json());
// ================================================
// static serve from server and client build
// ================================================
app.use(express.static(path.join(__dirname, '../client/build')));
// compress responses
// use compressions middleware for static files and res send
app.use(compression());
// ================================================
// Middleware
// ================================================
// morgan logs middleware
app.use(morgan('dev'));
// helmet security headers
app.use(helmet());
// disable Express mention in reasponse header
app.disable('x-powered-by');
// ===============================================
// User Endpoints
// ================================================
app.post('/api-v1/user', createUser);
app.get('/api-v1/user', getAllUsers);
app.get('/api-v1/user/:id', getSingleUser);
app.put('/api-v1/user/:id', updateUser);
app.delete('/api-v1/user/:id', deleteUser);
app.post('/api-v1/user/login', loginUser);
// ================================================
// Department Endpoints
// ================================================
app.post('/api-v1/department', createDepartment);
app.get('/api-v1/department', getAllDepartments);
app.get('/api-v1/department/:id', getSingleDepartment);
app.put('/api-v1/department/:id', updateDepartmentData);
app.delete('/api-v1/department/:id', deleteDepartment);
// Handles any requests that don't match the ones above
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, '../client/build/index.html'));
});
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, '../client/build/index.html'));
});
// ================================================
// Server start
// ================================================
app.listen(SERVER_PORT, "ABC.ABC.0.ABC", () => {
console.log(`Server running and listening on port ${SERVER_PORT}...`);
});
The errors that I get:
error in console

How to separate all of socket.io to a different file

Right now, I have app.js where I have my usual code and my socket.io code. But what I want to do is, separate every single code of socket.io into 1 different file and require that socket.io code from the different file into my main app.js. Is there any way to do it writing 2/3 lines of code into my app.js to require socket.io from a different file?
Note: I do not want to write any of my socket.io code into my app.js so I do not know if it would be possible to require('....') it into my app.js from a different file. Ideally want to separate everything within io.on('connection'){}
const express = require('express');
const http = require('http'); // socket.io is created upon http server. A way to create server
const cors = require('cors');
const {Server} = require('socket.io');
const app = express();
app.use(cors());
const server = http.createServer(app); // this is to create http server with express for socket.io
const io = new Server(server, {
cors: {
origin: "http://localhost:3000",
methods: ["GET", "POST"]
}
});
io.on("connection", (socket) => {
socket.on("newUser", (username) => {
addNewUser(username, socket.id);
console.log('connect print: '); printUsers();
})
socket.on("disconnect", () => {
removeUser(socket.id);
console.log('disconnect print: '); printUsers();
});
})
server.listen(3001, () => {
console.log('server listening on port 3001');
})
There would be a few way to do this but something like below should work.
In your new file, use module.exports to export an object containing any functions or objects you want to export:
//socketio.js
module.exports = {
getIo: (server) => {
const io = new Server(server, {
//...
});
io.on("connection", (socket) => {
//...
}
//your other functions
return io;
}
}
Then in your app.js, require it and use the object's properties:
//app.js
const socketio = require('./socketio.js');
//after creating your server etc
const io = socketio.getIo(server);

Why does my express router not respond to my get request?

So i have made a simple express app, but i have been trying for several hours to get a response to a simple get request when i visit http://localhost:3000/
This is my app.js
// IMPORTS
const express = require('express')
const mongoose = require('mongoose')
const customerRouter = require('./routes/customerRoute.js')
const app = express()
const PORT = 3000
// CONNECTION
mongoose.connect('mongodb://localhost/Customers', {useUnifiedTopology: true })
mongoose.connection.on('open', () => {console.log('Connected to database.')})
//APP USE ROUTES AND JSON
app.use(express.json)
app.use('/customers',customerRouter)
app.get('/', (req, res) => {
res.send('Home')
})
// APP PORT SET
app.listen(PORT)
console.log('Server started on port 3000')
This is my routes file
const express = require('express')
const router = express.Router()
console.log('into the router')
router.get('/', (req, res) => {
console.log('GET request')
})
module.exports = router
Substitute app.use(express.json) with app.use(express.json()) and everything will work. You have a mistake in this middleware that parses incoming requests with JSON payloads.
Source: express docs
You made a mistake in middleware app.use(express.json()) is a function not a property of the express object.

NextJS throwing 404 when deployed to Vercel

I have a custom express server that I'm using with NextJS.
Everything works just fine when I'm developing locally, but when I deploy to Vercel, I catch 404s whenever I try to access my backend API.
What could be going wrong? Here's my server.ts:
import express from 'express';
import next from 'next';
import bodyParser from 'body-parser';
import { connectDbs } from './config/db';
import { listingsRouter } from './routes';
const PORT = process.env.PORT || 3003;
const dbs = ['mydb'];
const dev = process.env.NODE_DEV !== 'production';
const nextApp = next({ dev });
const handle = nextApp.getRequestHandler();
const applyMiddleware = (app) => {
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
};
const applyRoutes = (app) => {
app.use('/api/listings', listingsRouter);
};
const startServer = async () => {
await nextApp.prepare();
const app = express();
applyMiddleware(app);
applyRoutes(app);
app.get('*', (req, res) => handle(req, res));
await connectDbs(dbs);
app.listen(PORT, () => console.log(`App listening on port ${PORT}`));
};
startServer();
The Next.js documentation for custom servers:
A custom server cannot be deployed on Vercel, the platform Next.js was made for.
Source: Custom Server
Even though you can't deploy a custom server, you generally don't need to do so because Next.js supports Serverless Functions using the /pages/api directory.
Source: API Routes
Also take a look at this Guide explaining how to convert custom Next.js server to routes:
Source: Server to Routes Guide

Why am I not able to access the express server from a different file?

I have set up an express server as follows (inside of server.js ) :
const app = express();
.........
.....
const PORT = process.env.PORT || 5000;
const server = app.listen(PORT, () =>
console.log(`Server started on port ${PORT}`)
);
module.exports = server;
Inside of another file socket.js:
const server = require("./server");
const socketio = require("socket.io");
const io = socketio(server);
io.on("connection", function (socket) {
console.log("A user just joined!");
socket.on("disconnect", () => {
console.log("A socket just left!");
});
});
For some reason I get an error in my console while trying to connect to the socketio on the client:
GET http://localhost:3000/socket.io/?EIO=3&transport=polling&t=N8-d7Q4 404 (Not Found)
The error does not occur if I execute everything in a single file (without exporting the server):
const PORT = process.env.PORT || 5000;
const server = app.listen(PORT, () =>
console.log(`Server started on port ${PORT}`)
);
const socketio = require("socket.io");
const io = socketio(server);
io.on("connection", function (socket) {
console.log("A user just joined!");
socket.on("disconnect", () => {
console.log("A socket just left!");
});
});
I don't understand what's wrong. Does module.exports not work with the express server or is this is a socketio issue ?
It appears you're not loading socket.js at all. When you had only the one file, you just did node app.js and that would work fine. But, if you do node app.js with your two files, then there's nothing to ever load socket.js at all. In fact, the way you have the two files laid out, you would have to do:
node socket.js
to initialize things. Then, socket.js does a require('./app.js') to get app.js loaded.
I was wondering if it's impossible to module.exports = server at all
Yes, you can freely export the server and you are exporting it.
Another way of doing things is to still have app.js be your main file that you load to start up your app and you load socket.js from there and pass it the server object so it can use it.
// app.js
const server = const server = app.listen(...);
// load socket.js and pass it our server
require('./socket.js')(server);
Then in socket.js:
// socket.js
const socketio = require("socket.io");
module.exports = function(server) {
const io = socketio(server);
// rest of your module code here
}

Categories