NodeJs - VueJs - 无法在生产中获取/路由

NodeJs - VueJs - Cannot GET /routes in production

我想将使用 NodeJs (express) 和 VueJs (2.6.11) 开发的网站投入生产。

我的文件夹看起来像这样:

/MyNodeJsApp
     - MyVueJsApp

我的 vue.config.js

里有这个
outputDir: path.resolve(__dirname, "../public")

所以当我 npm run build 它进入我项目根目录的 public 目录。

我的server.js就是这样:

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);
});

我的 Nodejs api 中的所有路由都包含相同的前缀 /api/,如下所示:

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);
  };

这是我的 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

当我访问 localhost:3000 网站时,该网站运行良好,我可以浏览该网站,每个页面都正确加载了正确的数据。所以我的 VueJs 前台工作正常。

但是当我尝试刷新页面时,我得到 Cannot GET /pagename

我尝试了多种解决方案,更改了我的路由名称,更改了我在 server.js 中导入它们的方式,我总是遇到同样的错误。

根据 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!

解决这个问题

对于 Node.js/Express,考虑使用 connect-history-api-fallback middleware.

遵循文档

安装插件

npm install --save connect-history-api-fallback

导入库

var history = require('connect-history-api-fallback');

添加为中间件

var express = require('express');

var app = express();
app.use(history({
    index: '/home.html'
});