Vue, Express приложение не пересылает запросы в индекс. html в режиме истории во время развертывания Heroku - PullRequest
0 голосов
/ 12 апреля 2020

TL; DR: Нажатие на это https://linkify.herokuapp.com/login дает not found error, хотя я могу от go до https://linkify.herokuapp.com и увидеть браузер показывает https://linkify.herokuapp.com/login после того, как я нажму на кнопку входа в навигационной панели.


Я пытаюсь развернуть простое приложение на https://linkify.herokuapp.com и в настоящее время сталкиваюсь с проблемами в истории API и маршрутизации сервера.

Если вы go перейдите по этой ссылке и linkify.herokuapp.com и перейдите по различным ссылкам на панели навигации, и вы увидите, что URL-адрес в браузере изменяется. Например, если вы нажмете на кнопку «Войти», вы увидите, что URL в браузере изменится на https://linkify.herokuapp.com/login.

Теперь, если вы отправите запрос на сервер, чтобы получить страницу входа, нажав здесь https://linkify.herokuapp.com/login, вы получите сообщение об ошибке.

Я предполагаю, что это потому, что маршруты vue не являются реальными URL-адресами и выдают ошибку «Не найдено» при вводе. У меня есть / логин маршрут. Когда я go на это представление, я могу видеть на Chrome, что URL-адрес ссылки https://linkify.herokuapp.com/login. Если я нажимаю Enter, я получаю 404 запроса не найдено. Я попробовал следующий фрагмент кода, чтобы получить все запросы для получения индекса. html страница, но я все еще получаю not found ошибку.

// Serve static assets (build folder) if in production
if (process.env.NODE_ENV === "production") {
   // Set static folder
   app.use(express.static(path.resolve(__dirname,"..","client","build")));
   app.get("*", (req, res) => {
       res.sendFile(path.resolve(__dirname,"..", "client", "build", "index.html"));
   });
 }
}

Я не думаю, что это проблема из-за Heroku, но я включаю его журналы на всякий случай. Любая помощь приветствуется.

Ниже приведен мой маршрутизатор / индекс. js

import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from '../views/Home.vue';
import Login from '../views/Login.vue';
import Register from '../views/Register.vue';
import store from '../store/index';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home,
    meta: {
      title: 'Home - Linkify',
      metaTags: [
        {
          name: 'description',
          content: 'The home page of Linkify'
        },
        {
          property: 'og:description',
          content: 'The home page of Linkify'
        }
      ]
    },
  },
  {
    path: '/login',
    name: 'Login',
    component: Login,
    beforeEnter: (to, from, next) => {
      store.dispatch('fetchAccessToken');
      if (store.state.accessToken) {
        next('/manage');
      }
      else {
        next();
      }
    },
  meta: {
    title: 'Login - Linkify',
    metaTags: [
      {
        name: 'description',
        content: 'The login page of Linkify'
      },
      {
        property: 'og:description',
        content: 'The login page of Linkify'
      }
    ]
  },
},
  {
    path: '/register',
    name: 'Register',
    component: Register,
    meta: {
      title: 'Register - Linkify',
      metaTags: [
        {
          name: 'description',
          content: 'The register page of Linkify'
        },
        {
          property: 'og:description',
          content: 'The register page of Linkify'
        }
      ]
    }   
  }, {
    path: '*',
    name: '404', /*Serve this route for pages not found*/
    component: () => import(/* webpackChunkName: "pagenoutfound" */ '../views/PageNotFound.vue'),
  }
];

const router = new VueRouter({
  routes,
  mode: 'history'
});

});


export default router;

ниже из моего приложения. vue, где я монтирую приложение

...
new Vue({
  router,
  store,
  render: createEle => createEle(App)
}).$mount('#app-container');
...

index. html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <meta name="mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="default">
  <link rel="icon" href="/favicon.ico">
  <meta name="description" content="URL Shortener ">
  <meta name="keywords" content="URL,Shortener,Analytics,Fraud, Detection">
  <meta name="author" content="Yigit Alparslan">
  <link rel="manifest" href="/manifest.json">
  <link rel="apple-touch-icon" sizes="57x57" href="/img/icons/apple-icon-57x57.png">
  <link rel="apple-touch-icon" sizes="60x60" href="/img/icons/apple-icon-60x60.png">
  <link rel="apple-touch-icon" sizes="72x72" href="/img/icons/apple-icon-72x72.png">
  <link rel="apple-touch-icon" sizes="76x76" href="/img/icons/apple-icon-76x76.png">
  <link rel="apple-touch-icon" sizes="114x114" href="/img/icons/apple-icon-114x114.png">
  <link rel="apple-touch-icon" sizes="120x120" href="/img/icons/apple-icon-120x120.png">
  <link rel="apple-touch-icon" sizes="144x144" href="/img/icons/apple-icon-144x144.png">
  <link rel="apple-touch-icon" sizes="152x152" href="/img/icons/apple-icon-152x152.png">
  <link rel="apple-touch-icon" sizes="180x180" href=".img/icons/apple-icon-180x180.png">
  <link rel="icon" type="image/png" sizes="192x192" href="/img/icons/android-icon-192x192.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/img/icons/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="96x96" href="/img/icons/favicon-96x96.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/img/icons/favicon-16x16.png">
  <meta name="msapplication-TileColor" content="#ffffff">
  <meta name="msapplication-TileImage" content="/img/icons/ms-icon-144x144.png">
  <meta name="theme-color" content="#ffffff">

  <title><%= htmlWebpackPlugin.options.title %></title>
</head>

<body>
  <noscript>
    <strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
      Please enable it to continue.</strong>
  </noscript>
  <div id="app-container"></div>
  <!-- built files will be auto injected -->
</body>

</html>

server. js

// Dependencies
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const morgan = require('morgan');
const mongoose = require('mongoose')
const path = require('path')
const passport = require("passport");
var device = require('express-device');
const cookieParser = require("cookie-parser");
const session = require("express-session");
const flash = require("express-flash");
const layout = require("express-layout");
const { check } = require("express-validator");
const helmet = require('helmet');
const serveStatic = require('serve-static');
const history = require('connect-history-api-fallback'); // Adding history redirects the /ggl7283 to /index.html

// Endpoints import
const home = require('./endpoints/home');
const shorten = require('./endpoints/shorten');
const geturls = require('./endpoints/geturls');
const redirect = require('./endpoints/redirect');
const login = require('./endpoints/login');
const register = require('./endpoints/register');
const savecustomurl = require('./endpoints/savecustomurl');
const generateqrcode = require('./endpoints/generateqrcode');
const { postcontact } = require('./endpoints/contact');

// Server setup
const app = express();

// Passport middleware
app.use(passport.initialize());

// Passport config
require("./config/passport")(passport);

// Define all middlewares
const middlewares = [
  helmet(),
  layout(),
  express.static(path.join(__dirname, "..", "client", "public")),
  bodyParser.urlencoded({ extended: true }),
  bodyParser.json(),
  flash(),
  cors(),
  device.capture(),
  morgan('tiny'),
  history()

];
app.use(middlewares);

// Capture device info: This will include a .device 
// field to each request object
device.enableDeviceHelpers(app)

const port = process.env.PORT || 5000;

// Database setup
const { MONGODB } = require('./config/keys.js');
mongoose
  .connect(MONGODB, { useNewUrlParser: true, useUnifiedTopology: true })
  .then(() => {

    console.log('MongoDB Connected');
  })
  .catch(() => {
    console.log('MongoDB failed to connect')
  })

// Endpoints setup
app.get('/', home);
app.get('/:shorturl', redirect);
app.post('/api/login', login);
app.post('/api/register', register);

// Serve static assets (build folder) if in production  
if (process.env.NODE_ENV === "production") {
  app.use(serveStatic(path.join(__dirname, '..', 'client', 'dist')));
  app.get("*", (req, res) => {
    res.sendFile(path.resolve(__dirname, "..","client", "dist", "index.html"));
  });
}

// Server run
app.listen(port, () => {
  console.log(`Server listening on port ${port}`);
});

Root пакет уровня. json

{
  "name": "linkify.herokuapp.com",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "heroku-prebuild": "npm install --prefix server && npm install --prefix client && npm run build --prefix client",
    "start": "npm start --prefix server",
    "client": "npm run serve --prefix client",
    "server":"npm run server --prefix server"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/ya332/url-shortener.git"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/ya332/url-shortener/issues"
  },
  "homepage": "https://github.com/ya332/url-shortener#readme"
}

Приложение структура

>package.json
>server
   >server.js
>client
   >dist
       >img/icons (all the icons)
   >public
   >index.html
   >manifest.json
   >favicon.ico
   >src>components

герои бревна - хвост

2020-04-12T04:45:13.187836+00:00 heroku[web.1]: Restarting
2020-04-12T04:45:13.190934+00:00 heroku[web.1]: State changed from up to starting
2020-04-12T04:45:37.259512+00:00 app[web.1]:
2020-04-12T04:45:37.259579+00:00 app[web.1]: > linkify.herokuapp.com@1.0.0 start /app
2020-04-12T04:45:37.259585+00:00 app[web.1]: > npm start --prefix server
2020-04-12T04:45:37.259585+00:00 app[web.1]:
2020-04-12T04:45:37.573868+00:00 app[web.1]:
2020-04-12T04:45:37.573915+00:00 app[web.1]: > linkify@1.0.0 start /app/server
2020-04-12T04:45:37.573916+00:00 app[web.1]: > node -r dotenv/config server.js
2020-04-12T04:45:37.573916+00:00 app[web.1]:
2020-04-12T04:45:38.656416+00:00 app[web.1]: Warning: connect.session() MemoryStore is not
2020-04-12T04:45:38.656431+00:00 app[web.1]: designed for a production
environment, as it will leak
2020-04-12T04:45:38.656432+00:00 app[web.1]: memory, and will not scale past a single process.
2020-04-12T04:45:38.668645+00:00 app[web.1]: Server listening on port 18065
2020-04-12T04:45:38.796155+00:00 app[web.1]: MongoDB Connected
2020-04-12T04:45:38.932110+00:00 heroku[web.1]: State changed from starting to up
2020-04-12T04:45:43.164498+00:00 heroku[router]: at=info method=GET path="/" host=linkify.herokuapp.com request_id=345bf302-9037-40c8-8fdd-d284ca7207b1 fwd="72.94.180.182" dyno=web.1 connect=0ms service=86ms status=304 bytes=430 protocol=https
2020-04-12T04:45:43.618951+00:00 heroku[router]: at=info method=GET path="/manifest.json" host=linkify.herokuapp.com request_id=9e10b1ea-7233-4cbe-8974-131430f1a8a5 fwd="72.94.180.182" dyno=web.1 connect=1ms service=6ms status=304 bytes=430 protocol=https
2020-04-12T04:45:43.641271+00:00 heroku[router]: at=info method=GET path="/favicon.ico" host=linkify.herokuapp.com request_id=78023e22-64eb-4685-8085-bf8de5bb2145 fwd="72.94.180.182" dyno=web.1 connect=0ms service=28ms status=200 bytes=1620 protocol=https
2020-04-12T04:45:43.719714+00:00 heroku[router]: at=info method=GET path="/img/icons/favicon-32x32.png" host=linkify.herokuapp.com request_id=f1a3daa0-6ee0-474e-9672-e38698134d5e fwd="72.94.180.182" dyno=web.1 connect=0ms service=3ms status=304 bytes=430 protocol=https
2020-04-12T04:45:43.691637+00:00 heroku[router]: at=info method=GET path="/img/icons/android-icon-144x144.png" host=linkify.herokuapp.com request_id=39ca47e4-9653-4858-aed0-5d40deb3fd6d fwd="72.94.180.182" dyno=web.1 connect=0ms service=21ms status=304 bytes=431 protocol=https
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...