I want to put in production my website developped in NodeJs (express) and VueJs (2.6.11).
My Folder look like that :
/MyNodeJsApp
- MyVueJsApp
I have this in my vue.config.js
outputDir: path.resolve(__dirname, "../public")
So when I npm run build
it goes on a public directory at the root of my project.
My server.js is like that :
const bodyParser = require("body-parser");
var cors = require('cors')
require('rootpath')();
const basicAuth = require('app/helpers/basic-auth');
const errorHandler = require('app/helpers/error-handler');
const app = express();
// parse requests of content-type: application/json
app.use(bodyParser.json());
app.use(express.static(__dirname + '/public'));
// parse requests of content-type: application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// Allow cors
app.use(cors())
// use basic HTTP auth to secure the api
app.use(basicAuth);
// global error handler
app.use(errorHandler);
// all Page routes
require("./app/routes/pageitem.routes.js")(app);
require("./app/routes/actualite.routes.js")(app);
require("./app/routes/user.routes.js")(app);
require("./app/routes/contact.routes.js")(app);
//We'll use the public directory to serve the Vue app
app.use(express.static('public'));
// set port, listen for requests
const port = 3000;
const server = app.listen(port, function () {
console.log('Server listening on port ' + port);
});
All the routes in my Nodejs api contain the same prefixe /api/
like so :
module.exports = app => {
const actualites = require("../controllers/actualite.controller.js");
// Retrieve all Pages
app.get("/api/actualites", actualites.findAll);
app.get("/api/actualites/type", actualites.getAllType);
app.get("/api/actualites/type/:type", actualites.findFromType);
// Retrieve a single Page with customerId
app.get("/api/actualites/:id", actualites.findOne);
};
This is my VueJsapp/router/index.js :
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
import Missions from '../views/Missions.vue'
import VousEtes from '../views/VousEtes.vue'
import VousEtesDesc from '../views/VousEtesDesc.vue'
import Actualite from '../views/Actualite.vue'
import Actualites from '../views/Actualites.vue'
import Service from '../views/Service.vue'
import Contact from '../components/Contact.vue'
import LoginPage from '../views/LoginPage.vue'
import Recrutement from '../views/Recrutement.vue'
Vue.use(VueRouter)
const routes = [
{
path: "/",
redirect: "/home"
},
{
path: '/home',
name: 'Home',
component: Home
},
{
path: '/missions',
name: 'Missions',
component: Missions
},
{
path: '/recrutement',
name: 'Recrutement',
component: Recrutement
},
{
path: '/vousEtes',
name: 'VousEtes',
component: VousEtes
},
{
path: '/vousEtesDesc/:id',
name: 'VousEtesDesc',
component: VousEtesDesc,
props(route) {
return {
pageid: route.params.id
};
},
},
{
path: '/service',
name: 'Service',
component: Service
},
{
path: '/actualites',
name: 'Actualites',
component: Actualites
},
{
path: '/actualite/:id',
name: 'Actualite',
component: Actualite,
props(route) {
return {
newsId: route.params.id
};
},
},
{
path: '/contact',
name: 'Contact',
component: Contact
},
{
path: '/login',
name: 'Login',
component: LoginPage
}
]
const router = new VueRouter({
mode: 'history',
scrollBehavior () {
return { x: 0, y: 0 }
},
routes
})
export default router
When I go to my localhost:3000 the website is working fine, I can navigate threw the website, every pages is loaded correctly with the right data. So my VueJs front is working fine.
But when I try to refresh a page, I get Cannot GET /pagename
I've try multiples solutions, changing my routes names, changing the way I import them in my server.js, I always get the same error.
As per the documentation
When using history mode, the URL will look "normal," e.g. http://oursite.com/user/id. Beautiful!
Here comes a problem, though: Since our app is a single page client side app, without a proper server configuration, the users will get a 404 error if they access http://oursite.com/user/id directly in their browser. Now that's ugly.
Not to worry: To fix the issue, all you need to do is add a simple catch-all fallback route to your server. If the URL doesn't match any static assets, it should serve the same index.html page that your app lives in. Beautiful, again!
To fix this
For Node.js/Express, consider using connect-history-api-fallback middleware.
Follow the documentation
To install the plugin
npm install --save connect-history-api-fallback
Import library
var history = require('connect-history-api-fallback');
Add as a middleware
var express = require('express');
var app = express();
app.use(history({
index: '/home.html'
});