Vue Router return 404 重访时 url

Vue Router return 404 when revisit to the url

我刚刚启用了 Vue 路由器历史记录模式。当我通过 v-href 或 href 访问 vue 路由时它工作正常。但是,当我尝试刷新该页面或直接从浏览器地址栏转到时,它只是 return 404。是否有接受 refresh/revisit 到 url 的选项?

以下是我的Vue路由配置

var router = new VueRouter({
  hashbang: false,
  history: true,
  mode: 'html5',
  linkActiveClass: "active",
  root:  '/user'
});

通过刷新页面,您正在使用当前 url 和服务器 returns 404 向服务器发出请求。您必须在 Web 框架或 Web 服务器级别处理此问题。

本文包含示例服务器配置: https://router.vuejs.org/guide/essentials/history-mode.html

我认为您忽略了 SPA 不是服务器端渲染。至少对于大多数人来说。因此,当您访问 /anything 时,您的 Web 服务器不会将其重定向到 index.html。但是,如果您单击任何 vuejs 路由器 link,它将起作用,因为 javascript 起作用了,而不是服务器端。

要解决这个问题,请使用 .htaccess 并将所有请求重定向到 index.html,就像这样

<ifModule mod_rewrite.c>
    RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</ifModule>

希望对大家有所帮助!

如果有人在作为应用程序后端的 .NET Core 中处理这个问题,一个不错的方法是在我们的 .NET Core 应用程序的 Startup.cs 中使用一个简单的回退处理程序:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
        ....Your configuration
      app.UseMvc(routes =>
      {
        routes.MapRoute(
                  name: "default",
                  template: "{controller=Home}/{action=Index}/{id?}");
      });
      //handle client side routes
      app.Run(async (context) =>
      {
        context.Response.ContentType = "text/html";
        await context.Response.SendFileAsync(Path.Combine(env.WebRootPath, "index.html"));
      });
    }
 }

更多详情:http://blog.manuelmejiajr.com/2017/10/letting-net-core-handle-client-routes.html

对于使用 Express 后端看到此内容的人,中间件 connect-history-api-fallback 是这样实现的

const express = require('express');
const history = require('connect-history-api-fallback');

const app = express(); 
app.use(history({
  index: '/' //whatever your home/index path is default is /index.html
}));

或使用本机节点

const http = require('http')
const fs = require('fs')
const httpPort = 80

http.createServer((req, res) => {
  fs.readFile('index.htm', 'utf-8', (err, content) => {
    if (err) {
      console.log('We cannot open "index.htm" file.')
    }

    res.writeHead(200, {
      'Content-Type': 'text/html; charset=utf-8'
    })

    res.end(content)
  })
}).listen(httpPort, () => {
  console.log('Server listening on: http://localhost:%s', httpPort)
})

两者都是 documentation 中的建议。

其他人也面临同样的问题,我才意识到

"book/:bookId/read"  // this will not work after page reload

和这个不一样

"/book/:bookId/read" // this is what works even after page reload

这当然是在遵循其他人提出的建议之后,更重要的是在您的应用程序服务器端捕获所有路由。 我实际上不知道为什么会这样,但是任何有想法的人都可以告诉我们。

如果您真的不关心 url 中的散列,您可以在路由器配置文件中将模式设置为散列:mode: 'hash' 无需设置服务器端即可正常工作。

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

哈希模式在 vue 中是默认的,所以即使你留空而不是 mode: 'hash' 它也应该可以工作。

我将 Razor Pages 与 .net core 2.2 一起使用,我开始工作了:

app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller}/{action=Index}/{id?}");

            routes.MapRoute(
                name: "spa-fallback",
                template: "{*url:regex(^((?!.css|.map|.js|sockjs).)*$)}",
                defaults: new { controller = "Index", action = "Index" });

        });

对于 Netlify,将以下内容添加到 public/_redirects 文件...

/*    /index.html   200

https://www.netlify.com/docs/redirects/#history-pushstate-and-single-page-apps

来晚了,但是.....

如果有人对此有兴趣,我只是这样做了:

  1. 将对已知客户端 URL 的请求重定向到索引(但仅已知客户端 URL ,这样,您可以为实际页面保留 404 -未找到 URLs)。您如何执行此操作取决于您的服务器。我当时用的是flask,只是多加了路由而已

  2. 给根vue元素添加一个属性

    <div id="content" redirect_to="{{redirect_to}}"></div>

我的视图函数将参数替换为 URL

请求的实际路线
  1. 在根 vue 组件中,检查此属性并检索其值,如下所示:

if (this.$el.attributes['redirect_to'].value !== "") path = this.$el.attributes['redirect_to'].value

  1. 使用属性
  2. 的值调用$router.push

this.$router.push(path).catch(err => {})

(需要捕获,否则路由器将抛出 NavigationDuplicated 错误。)

我这样做是因为 SPA 中的整个 url 点是因为它们指向特定资源,我希望我的用户能够使用 URLs 返回到那些相同的资源。

希望这可以帮助某人或为他们指明正确的方向,使其能够满足他们的特定需求。

甚至更好(在 Ubuntu 上)如果你有 root 权限将修改 /etc/apache2/apache2.conf,因为即使 Apache 自己 discourage 在这种情况下使用 .htaccess .

请注意,首先,您必须做

sudo a2enmod rewrite

然后,将以下块添加到 /etc/apache2/apache2.conf

<Directory /var/www/html/>
        RewriteEngine On
        RewriteBase /
        RewriteRule ^index\.html$ - [L]
        RewriteCond %{REQUEST_FILENAME} !-f
        RewriteCond %{REQUEST_FILENAME} !-d
        RewriteRule . /index.html [L]
</Directory>

之后,做

sudo systemctl restart apache2

对我来说,这完美无缺,因为它不仅将 Vue 创建的路由重定向回 /,而且实际上将网站刷新到相同的路由,所以刷新后你仍然在相同的视图中.

如果任何人在尝试上述解决方案后仍面临问题,请查找以下方法。 如果你有 vue.config.js 其中有

module.exports = {
  publicPath: process.env.PUBLIC_URL || "", // <-- this is wrong
  ...
};

删除 vue.config.js 或尝试从导出对象中删除 publicPath。

如果您不想删除 publicPath,也可以尝试以下方法

module.exports = {
  publicPath: process.env.PUBLIC_URL || "/", default)
  transpileDependencies: ["vuetify"],
};

在我的案例中,它发生在 Azure CDN 下作为静态网站托管在 Azure Blob 存储中的 SPA 中。 以下问题的解决方案为我解决了这个问题(修复应用于 CDN 端点):

这太简单了,你只需要在你的服务器上添加这个配置:

Apache

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

那么如果你在 Nginx:

location / {
  try_files $uri $uri/ /index.html;
}

就这些了

有关详细信息,请访问此 Link

我也遇到了同样的问题。在路由中添加此代码后 -> web.php 问题已解决。

   Route::get('/{vue_capture?}', function () {
    return view('admin.dashboard');
})->where('vue_capture', '[\/\w\.-]*');

将此路线重定向到您的 parent blade 视图。

正如@SERPRO 所解释的那样,Vuejs、Angular、Reactjs 等都是基于单页应用程序 (SPA) 的概念构建的,所以我在 Apache 服务器上所做的只是告诉服务器为原点之后的任何路径值加载 index.html。以下是对我有用的更改。 在我的虚拟主机文件上,我添加了一个简单的重写规则以始终加载 index.html 而不是重定向。

RewriteEngine On
RewriteRule "^/auth/account/confirm" "/index.html"

因此,如果用户输入 http:///my-origin/account/confirm,服务器将加载绑定了 app.vue 文件的 index.html,以及 app.vue 文件路由器现在将选择路径 account/confirm 并确定要渲染的适当组件

然后运行

apachectl restart
service httpd restart

在我的例子中,404 错误不仅发生在页面重新加载时,也发生在使用浏览器的导航按钮时。
问题是路径中的特殊字符,如 äö 等。首先,路由与那些工作得很好,但是当使用浏览器导航按钮或在页面上重新加载时,无法再找到该页面。在我用普通字母替换特殊字符后,路由再次起作用。
也许这对其他人有帮助。

就我而言,我使用 Vue 自己的配置来解决这个问题。这里的想法是利用 pages 选项。所以在文件 vue.config.js 中,我们将添加以下代码示例:

module.exports = {
  pages: {
    // This is our main page which refers to the main Javascript file
    index: "src/main.js", 
    // Next, we list all other pages in the application, 
    // and let all of them refer to the main Javascript file as well.
    other_page: "src/main.js",
  },
};

使用此实现,如果我们停留在 other_page 并重新加载,应用程序仍然可以运行,不会显示任何 404 错误。

只需将代码放在同一文件夹中的 .htaccess 文件中即可。无需重启或 Apache 重启。

RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]

就我而言,我是通过虚拟主机处理的:

阿帕奇

转到 /etc/apache2/sites-available 并使用您的域名克隆 000-default.confapp.abc.com.conf 并通过 sudo nano app.abc.com.conf 打开它然后放置在代码段下方:

Vue 文档参考:Click here
Whosebug 参考:
<VirtualHost *:80>

ServerName app.abc.com
DocumentRoot /var/www/html/project_name/dist/

ErrorLog ${APACHE_LOG_DIR}/app.abc.com.error.log
CustomLog ${APACHE_LOG_DIR}/app.abc.com.access.log combined

  <Directory /var/www/html/project_name/dist>
        FallbackResource /index.html  
  </Directory>

</VirtualHost>
Niginx Vue Cli (SPA) 虚拟主机:
Vue 文档参考:Click here
server {
        listen 80;
        root /var/www/html/project_name/dist;
        server_name app.abc.com;
        index index.html index.htm index.php;
        location / {
             try_files $uri $uri/ /index.html;
        }
}

注意: 在 ubuntu 服务器上测试