I’m trying to make a register page for my Vue Express app and the client as well as server side are running and in Postman it shows that it is receiving the request, but in my browser I still have Cannot GET/ Register. Node version is 16.13.2 and Vue is @vue/cli 5.0.1. Also, I don’t know if this is related, but for my router I try to import from vue-router, but then I look at node_modules I don’t see it anywhere. Any help would be appreciated and my code is as follows:
app.js
console.log('hello') const express = require('express') //const router = express.Router() const bodyParser = require('body-parser') const cors = require('cors') const morgan = require('morgan') //app assigned to express server and functionality below const app = express() app.use(morgan('combine')) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: true })); app.use(cors()) app.get('/', function(req, res) { res.send({ message: 'Welcome' }) }) app.post('/register', function (req, res) { res.send({ message: 'Hello, you have been registered. Enjoy!' }) }) app.listen(process.env.PORT || 8081)
index.js
import Vue from "vue" import Router from "vue-router" Vue.use(Router) import Hello from '@/components/HelloWorld.vue' import Register from '@/components/Register.vue' export default new Router({ routes: [ { path: '/', name: 'Hello', component: Hello }, { path: '/register', name: 'register', component: Register } ] })
Register.vue
<template> <div> <h1>Register</h1> <input type="email" name="email" v-model="email" placeholder="email" /> <br> <input type="password" name="password" v-model="password" placeholder="password" /> <br> <button @click="register"> Register </button> </div> </template> <script> import AuthenticationService from "@/services/AuthenticationService" export default { data () { return { email: '', password: '' } }, methods: { async register () { const response = await AuthenticationService.register({ email: this.email, password: this.password }) console.log(response.data) } }, } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> </style>
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
First of all, you need to take into account that the frontend part of your app is running separately from your backend (even if they are in the same machine), so the router for the frontend is not related to the backend, that is why you are able to hit the server using postman, but nothing gets render.
Here is what I’m seeing:
- You have the backend running and listening for 2 locations:
GET "/"
, andPOST "/register"
. - If you run the server and then go to the root (/) in the browser, you
will see the message in the console but nothing rendered, nothing is
rendered because the server is just responding with a message. - When you test the POST with postman, the server is responding with a message (nothing is rendered either), because the server is not “serving” any content.
If you want the users to see something while navigating to any route, the server needs to return something that the browser can show (your frontend). With Vue, you have a single page application which means that you don’t need a server checking what to serve with each location, you have the internal Vue router for that, but you need the server to return your index at some point.
For this you will need to serve your index.html
as a static file, so you will need to add:
app.use(express.static("PathToTheFolderContainingYourVueApplication"))
And then in any route you should start serving your index.html
in your case (and with many vue apps) you want to serve the index for any route that the server doesn’t know, because the Vue router could decide to show something and of course your Vue app should handled the scenario where a route that no one knows is being hit (the famous 404).
Your code will look something like this:
const express = require('express') const bodyParser = require('body-parser') const cors = require('cors') const morgan = require('morgan') // Here you need the path to your vue index // __dirname is pointing to the current path where this node process is running // check the docs for __dirname https://nodejs.org/docs/latest/api/modules.html#__dirname const path = __dirname + '/PathToTheFolderContainingYourVueIndex'; const app = express(); app.use(express.static(path)); // express now knows that it will serve files from here //app assigned to express server and functionality below const app = express() app.use(morgan('combine')) app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: true })); app.use(cors()) // I'm commenting this, because you want Vue to show somwthing in this route // app.get('/', function(req, res) { // res.send({ // message: 'Welcome' // }) // }) // leaving this because you want the server handling this route app.post('/register', function (req, res) { res.send({ message: 'Hello, you have been registered. Enjoy!' }) }) // The routes are solved in order, if none of the previous ones was hit, then this one will be checked // The * is telling express that any route will be accepted (that is why this is the last one) app.get('*', function(req, res) { // The server doesn't know what to show, but you will return the Vue index and then let the vue-router do its thing res.sendFile(path + "index.html"); }); app.listen(process.env.PORT || 8081)
Now you can try in the browser to go to any route handled by your Vue app (I didn’t test the code myself but I assume you can do it and spot any issue).
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0