Vue 路由器历史记录模式返回 404 错误

Vue router history-mode returing 404 error

我在 tomcat 中有一个具有历史模式 运行 的 vue 应用程序。 当访问 www.mywebapp.com/faq 或 mywebapp.com/other 或 ../post/99 等时,它首先似乎工作正常。刷新页面似乎也能正常工作。

然而,当我仔细查看浏览器控制台时,我发现我收到了一条错误消息。

"Failed to load resource: the server responded with a status of 404 ()"

页面在重定向我之前一瞬间返回 404 错误,然后页面加载。

在非常慢的互联网连接上,404 错误在加载之前会存在更长的时间。

有人知道我在这里缺少什么吗?我已经添加了以下代码来尝试处理它但没有成功。

我的路由器是这样的:

  export const router = new Router({
  mode: 'history',
  base: '/',
  routes: [
  {
  name: 'home',
  path: '/',
  component: Home
  },
  ....,
  {
   path: '*',
  component: ErrorLanding,
  name: 'NotFound'
  },
  ],
  scrollBehavior(to, from, savedPosition) {
      return {x:0, y: 0}
  }
  });
  router.beforeEach((to, from, next) => {
   const publicPages = ['/', '/login', '/register', 
       '/help', '/ticket', '/about' ];
   const authRequired = !publicPages.includes(to.path);
   const loggedIn = localStorage.getItem('user');
    const redirect = to.path;

   if (authRequired && loggedIn === null) {
    if(to.meta.authRequired === false) {
      next();
    }
    else
    next({ name: 'Login', query: { redirect: redirect } });

    } else {
    next();
    }
   });

我的 vue.config.js 看起来像这样:

   module.exports = {
   devServer: {
   port: 80,     
   proxy: "http://localhost/*"
   },
   publicPath: process.env.NODE_ENV === 'production'
   ? '/'
   : '/'
   }

最后,我在 dist/ROOT/WEB-INF/ 中有一个 web.xml 文件,其中包含以下代码:

  <?xml version="1.0" encoding="ISO-8859-1"?>
   <web-app xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
   version="3.0" 
   metadata-complete="true">
  <display-name>my app</display-name>
  <description>
     this is my app description
  </description>
  <error-page>  
   <error-code>404</error-code>  
   <location>/</location>  
  </error-page>  
</web-app>

更新

当我将这行代码添加到 server.xml

   <Valve 
   className="org.apache.catalina.valves.rewrite.RewriteValve"/>

并创建一个 rewrite.config 文件,我将其添加到 Catalina/localhost/ 有了这个信息:

   RewriteCond %{REQUEST_PATH} !-f
   RewriteRule ^/(.*) /index.html 

它正在运行,我没有再收到任何错误消息。 但现在我有一个新问题。我通过 Vuex 填充的数组正在返回无限循环。怎么会这样?

更新

我已尝试将其添加到 rewrite.config 文件中:

RewriteRule ^/api1/ - [L,NC]
RewriteRule ^/api2/ - [L,NC]
RewriteRule ^/api3/ - [L,NC]
RewriteRule ^/api4/ - [L,NC]
RewriteRule ^/api5/ - [L,NC]
RewriteRule ^/api6/ - [L,NC]
RewriteCond %{REQUEST_PATH} !-f
RewriteRule ^/(.*) /index.html

更新 已解决 必须将以下内容添加到 rewrite.config 文件中。

 RewriteRule ^/myapi1/.* - [L,NC]
 RewriteRule ^/myapi2/.* - [L,NC]
 RewriteRule ^/myapi3/.* - [L,NC]
 RewriteRule ^/myapi4/.* - [L,NC]
 RewriteRule ^/myapi5/.* - [L,NC]
 RewriteRule ^/host-manager/.* - [L,NC]
 RewriteRule ^/manager/.* - [L,NC]
 RewriteCond %{REQUEST_PATH} !-f
 RewriteRule ^/(.*) /index.html

非常感谢@Michal Levy 的帮助!!

问题是使用 Vue Router 的历史模式导致的,在 docs

中有很好的描述

When using history mode, the URL will look "normal," e.g. http://oursite.com/user/id. 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. 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.

还有很多示例如何为很多服务器执行此操作 - 不适用于 Tomcat 但是...

要在 Tomcat 中配置“SPA 回退”(此的通用名称),您必须:

  1. server.xml
  2. 中配置 RewriteValve

编辑 ~/conf/server.xml 以在主机部分添加以下阀门,如下所示:

<Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true">
  <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
</Host>
  1. rewrite.config
  2. 中写入重写规则

创建目录结构 — ~/conf/Catalina/localhost/ 并在其中创建 rewrite.config 文件,内容如下:

RewriteCond %{REQUEST_PATH} !-f
RewriteRule ^/(.*) /index.html

Source

注意: 请注意,上面的重写规则会导致您的服务器 return index.html 对于任何与“常规文件”不匹配的请求(请参阅 Rewrite Valve Docs).所以 如果 你的服务器也服务于某种 API (例如 REST),你需要修改重写规则不要重写请求到 API.

例如,如果您的 API 在 /api/... 上投放,您的重写规则应如下所示:

# match any URL starting with `/api/`, do not rewrite and don't process other rules...
RewriteRule ^/api/ - [L]
RewriteCond %{REQUEST_PATH} !-f
RewriteRule ^/(.*) /index.html

@Michal Levys 的回答是正确的,只是需要针对我的情况进行一些小的调整。 要解决此问题,必须将以下内容添加到 rewrite.config.

  RewriteRule ^/myapi1/.* - [L,NC]
  RewriteRule ^/myapi2/.* - [L,NC]
  RewriteRule ^/myapi3/.* - [L,NC]
  RewriteRule ^/myapi4/.* - [L,NC]
  RewriteRule ^/myapi5/.* - [L,NC]
  RewriteRule ^/host-manager/.* - [L,NC]
  RewriteRule ^/manager/.* - [L,NC]
  RewriteCond %{REQUEST_PATH} !-f
  RewriteRule ^/(.*) /index.html