Vue 项目布署后,刷新页面(或跳转页面)出现 404 解决办法

Vue 项目布署后,刷新页面(或跳转页面)出现 404

    • 问题背景
    • 为什么会出现404
    • 解决办法(两种)
      • 方法一:改变服务器配置
      • 方法二:改变路由模式
    • 单页应用(SPA)概念

问题背景

今天重新部署一个vue项目的时候,发现在刷新页面和请求跳转其他页面(非跟页面,也就是 /index.html)出现 404 错误。

在这里插入图片描述

为什么会出现404

看一下打包的 dist 文件

在这里插入图片描述
可以看到dist下只有一个 index.html 文件及一些静态资源,这个是因为Vue是单页应用(SPA),只有一个index.html作为入口文件,其它的路由都是通过JS来进行跳转

接下来看一下服务器的配置,以 nginx 为例

server {
  // 监听80端口
  listen 80;
  // 定义你的站点名称
  server_name website.com;
  // 根据请求 URI 设置配置
  location / {
      // 站点根目录,这里为 vue 构建出来的 dist 目录
      root   /www/dist;
      // 站点初始页为index.html 或 index.htm
      index  index.html index.htm;
  }
}

我们现在可以根据 nginx 配置得出,当我们在地址栏输入 website.com 时,这时会打开我们 dist 目录下的 index.html 文件,然后我们在跳转路由进入到 website.com/login

关键在这里,当我们在 website.com/login 页执行刷新操作,nginx location 是没有相关配置的,所以就会出现 404 的情况

为什么hash模式下没有问题

router hash 模式我们都知道是用符号#表示的,如 website.com/#/login, hash 的值为 #/login

它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对服务端完全没有影响,因此改变 hash 不会重新加载页面

hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 website.com/#/login 只有 website.com 会被包含在请求中 ,因此对于服务端来说,即使没有配置location,也不会返回404错误

解决办法(两种)

方法一:改变服务器配置

vue-router 官网地址

Apache

<IfModule mod_negotiation.c>
  Options -MultiViews
</IfModule>

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

也可以使用 FallbackResource 代替 mod_rewrite。

nginx

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

原生 Node.js

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

http
  .createServer((req, res) => {
    fs.readFile('index.html', 'utf-8', (err, content) => {
      if (err) {
        console.log('We cannot open "index.html" 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)
  })

Express + Node.js

对于 Node.js/Express,可以考虑使用 connect-history-api-fallback 中间件。

Internet Information Services (IIS)

  1. 安装 IIS UrlRewrite
  2. 在网站的根目录下创建一个 web.config 文件,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="Handle History Mode and custom 404/500" stopProcessing="true">
          <match url="(.*)" />
          <conditions logicalGrouping="MatchAll">
            <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
            <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
          </conditions>
          <action type="Rewrite" url="/" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>

Caddy v2

try_files {path} /

Caddy v1

rewrite {
    regexp .*
    to {path} /
}

Firebase hosting

将此添加到你的 firebase.json 中:

{
  "hosting": {
    "public": "dist",
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}

Netlify

创建一个 _redirects 文件,包含在你的部署文件中:

/* /index.html 200

在 vue-cli、nuxt 和 vite 项目中,这个文件通常放在名为 static 或 public 的目录下。

你可以在 Netlify 文档中找到更多关于语法的信息。你也可以创建一个 netlify.toml 来结合其他 Netlify 功能的重定向。

Vercel

在项目根目录创建一个vercel.json文件,内容如下:

{
  "rewrites": [{ "source": "/:path*", "destination": "/index.html" }]
}

Caveat

这有一个注意事项。你的服务器将不再报告 404 错误,因为现在所有未找到的路径都会显示你的 index.html 文件。为了解决这个问题,你应该在你的 Vue 应用程序中实现一个万能的路由来显示 404 页面。

const router = createRouter({
  history: createWebHistory(),
  routes: [{ path: '/:pathMatch(.*)', component: NotFoundComponent }],
})

方法二:改变路由模式

Hash 模式

hash 模式是用 createWebHashHistory() 创建的:

import { createRouter, createWebHashHistory } from 'vue-router'

const router = createRouter({
  history: createWebHashHistory(),
  routes: [
    //...
  ],
})

它在内部传递的实际 URL 之前使用了一个哈希字符(#)。由于这部分 URL 从未被发送到服务器,所以它不需要在服务器层面上进行任何特殊处理。不过,它在 SEO 中确实有不好的影响。如果你担心这个问题,可以使用 HTML5 模式。

HTML5 模式

用 createWebHistory() 创建 HTML5 模式,推荐使用这个模式:

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    //...
  ],
})

当使用这种历史模式时,URL 会看起来很 “正常”,例如 https://example.com/user/id。漂亮!

不过,问题来了。由于我们的应用是一个单页的客户端应用,如果没有适当的服务器配置,用户在浏览器中直接访问 https://example.com/user/id,就会得到一个 404 错误。这就尴尬了。

不用担心:要解决这个问题,你需要做的就是在你的服务器上添加一个简单的回退路由。如果 URL 不匹配任何静态资源,它应提供与你的应用程序中的 index.html 相同的页面。漂亮依旧!

因为我其他地方用到了重定向以及要取得上一个页面的地址,所以没有办法用 hash 模式,所以直接修改的服务器配置。
若没有我这样的限制的话,直接将路由模式改为 hash 即可。

单页应用(SPA)概念

单页应用

单页应用(single-page application),缩写SPA 是一种网络应用程序或网站的模型,它通过动态重写当前页面来与用户交互,而非传统的从服务器重新加载整个新页面。这种方法避免了页面之间切换打断用户体验,使应用程序更像一个桌面应用程序。在单页应用中,所有必要的代码(HTML、JavaScript和CSS)都通过单个页面的加载而检索,或者根据需要(通常是为响应用户操作)动态装载适当的资源并添加到页面。尽管可以用位置散列或HTML5历史API来提供应用程序中单独逻辑页面的感知和导航能力,但页面在过程中的任何时间点都不会重新加载,也不会将控制转移到其他页面

大白话来讲:

一个杯子,早上装的牛奶,中午装的是开水,晚上装的是茶,我们可以发现,变的始终是内容,而容器还是那个容器

当然,每种技术都有其利弊,单页应用也是如此

利:

  1. 无刷新体验,这个应该是最显著的有点,由于路由分发直接在浏览器端完成,页面是不刷新,对用户的响应非常及时,因此提升了用户体验

  2. 完全的前端组件化,前端开发不再以页面为单位,更多地采用组件化的思想,代码结构和组织方式更加规范化,便于修改和调整

弊:

  1. 首屏较长,要在一个页面上为用户提供产品的所有功能,在这个页面加载的时候,首先要加载大量的静态资源,这个加载时间相对比较长

  2. 不利于 SEO,单页页面,数据在前端渲染,就意味着没有 SEO,或者需要使用变通的方案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/86720.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【NX】NX二次开发BlockUI集列表的详细使用步骤

最近使用NX二次开发&#xff0c;需要用到集列表&#xff0c;也就是SetList这个控件&#xff0c;然而网上相关的资料和范例实在是太少&#xff0c;有幸找到《NX二次开发-BlockUI集列表的使用技巧》和《UG&#xff08;NX&#xff09;二次开发 BlockUI 集列表使用方法》&#xff0…

Vue Cli 脚手架安装

Vue Cli 脚手架安装 首先&#xff0c;改一下仓库地址&#xff0c;使用下面的命令cnpm淘宝镜像加速 npm install cnpm -g --registryhttps://registry.npm.taobao.org下载安装 vue 脚手架 npm install -g vue/cli查看 vue cli 脚手架是否安装成功&#xff0c;如果输入命令出现…

【业务功能篇77】微服务-OSS对象存储-上传下载图片

3. 图片管理 文件存储的几种方式 单体架构可以直接把图片存储在服务器中 但是在分布式环境下面直接存储在WEB服务器中的方式就不可取了&#xff0c;这时我们需要搭建独立的文件存储服务器。 3.1 开通阿里云服务 针对本系统中的相关的文件&#xff0c;图片&#xff0c;文本等…

Linux系统安全:NAT(SNAT、DNAT)

目录 一.NAT 二.SNAT 三.DNAT 一.NAT NAT: network address translation&#xff0c;支持PREROUTING&#xff0c;INPUT&#xff0c;OUTPUT&#xff0c;POSTROUTING四个链 请求报文&#xff1a;修改源/目标IP&#xff0c; 响应报文&#xff1a;修改源/目标IP&#xff0c;根据…

测试框架pytest教程(11)-pytestAPI

常量 pytest.__version__ #输出pytest版本 pytest.version_tuple #输出版本的元组形式 功能 pytest.approx pytest.approx 是一个用于进行数值近似比较的 pytest 断言工具。 在测试中&#xff0c;有时候需要对浮点数或其他具有小数部分的数值进行比较。然而&#xff0c;由于…

Linux面试笔试题(6)

91、6块300G的硬盘做raid5&#xff0c;新的设备容量是多大&#xff08;C&#xff09; A 900G B 1800G C 1500G D 300G 6300G−300G 1500G 由于一块硬盘用于奇偶校验&#xff0c;所以设备容量将是1500G. Raid 5是一种磁盘阵列&#xff0c;将数据分散到多个硬盘上以提高性能和可…

【⑬MySQL | 数据类型(一)】简介 | 整数 | 浮点 | 定点类型

前言 ✨欢迎来到小K的MySQL专栏&#xff0c;本节将为大家带来MySQL数据类型简介 | 整数 | 浮点 | 定点类型的分享✨ 目录 前言0.数据类型简介1 整数类型2 浮点类型3 定点类型4 日期/时间类型总结 0.数据类型简介 数据类型&#xff08;data_type&#xff09;是指系统中所允许的…

LeetCode算法递归类—二叉树中的最大路径和

目录 124. 二叉树中的最大路径和 - 力扣&#xff08;LeetCode&#xff09; 题解&#xff1a; 代码&#xff1a; 运行结果&#xff1a; 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该…

【图论】拓扑排序

一.定义 拓扑排序是一种对有向无环图&#xff08;DAG&#xff09;进行排序的算法&#xff0c;使得图中的每个顶点在排序中都位于其依赖的顶点之后。它通常用于表示一些任务之间的依赖关系&#xff0c;例如在一个项目中&#xff0c;某些任务必须在其他任务之前完成。 拓扑排序的…

SQL注入之延时注入

文章目录 延时注入是什么&#xff1f;延时注入获取数据库版本号 延时注入是什么&#xff1f; 延时注入就是利用sleep()函数通过if语句判断所写的语句真假&#xff0c;如果为真返回我们想要的东西&#xff08;例如&#xff1a;数据库的长度&#xff0c;数据库的名字等&#xff0…

认识负载均衡||WEBSHELL

目录 一、负载均衡 1.nginx负载均衡算法 2.nginx反向代理-负载均衡 二、webshell 1.构造不含数字和字母的webshell 2.如何绕过 一、负载均衡 1.nginx负载均衡算法 &#xff08;1&#xff09;轮询&#xff08;默认&#xff09;每个请求按时间顺序逐一分配到不同的后端服务&…

达梦数据库读写分离集群原理

概述 本文就达梦数据库读写分离原理进行介绍。 达梦读写分离集群特点&#xff1a; 可以配置8个即时备库或8个实时备库&#xff1b;读写操作自动分离、负载均衡&#xff1b;提供数据同步&#xff1b;备库故障自动处理&#xff0c;故障恢复自动数据同步等功能&#xff0c;也支持…

无涯教程-TensorFlow - Keras

Keras易于学习的高级Python库&#xff0c;可在TensorFlow框架上运行&#xff0c;它的重点是理解深度学习技术&#xff0c;如为神经网络创建层&#xff0c;以维护形状和数学细节的概念。框架的创建可以分为以下两种类型- 顺序API功能API 无涯教程将使用Jupyter Notebook执行和…

会计如何使用ChatGPT提高工作效率

文章目录 ChatGPT改变了会计行业微软重新定义了PC交互应对ChatGPT带来的冲击给财务人员的建议总结 ✍创作者&#xff1a;全栈弄潮儿 &#x1f3e1; 个人主页&#xff1a; 全栈弄潮儿的个人主页 &#x1f3d9;️ 个人社区&#xff0c;欢迎你的加入&#xff1a;全栈弄潮儿的个人社…

LInux之例行工作

目录 场景 单一执行例行任务 --- at&#xff08;一次性&#xff09; 安装 命令详解 语法格式 参数及作用 时间格式 案例 at命令执行过程分析 循环执行的例行性任务--crontab&#xff08;周期性&#xff09; crontd服务安装 linux 任务调度的工分类 crontab工作过程…

js案例:小球碰壁反弹

目录 一.效果预览图​编辑 解析 二.完整代码 代码讲解 html部分 js部分 一.效果预览图 解析 这个效果是为了以后&#xff08;过段时间会发的一个小游戏&#xff09;做js小游戏做准备的&#xff0c;基本结构是&#xff0c;定义两个div盒子&#xff0c;小盒子设置成圆球形状…

代码pytorch-adda-master跑通记录

前言 最近在学习迁移学习&#xff0c;ADDA算法&#xff0c;由于嫌自己写麻烦&#xff0c;准备先跑通别人的代码。 代码名称&#xff1a;pytorch-adda-master 博客&#xff1a;https://www.cnblogs.com/BlairGrowing/p/17020378.html github地址&#xff1a;https://github.com…

关于Springboot项目打包的配置问题

一、打包方式的不同致使jar包运行性能及docker部署的效率问题 1.1方式一 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><configuration><source&…

Flash 空间大小的选择以及8MB和8M bit单位与转换关系

他V hezkz17进数字音频系统研究开发交流答疑群(课题组) log打印 [09:54:27.565] FLASH_SIZE0x800000 这个是 8MB 字节 芯片手册Flash是以字节为单位 注意单位与转换关系 ifeq ($(FLASH_SIZE),0x100000) # 8M bits LOG_DUMP_SECTION_SIZE ? 0x10000 endif 0x1000001MB为 …
最新文章